@gem-sdk/swiper 0.0.15 → 0.0.17-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { a as getWindow, g as getDocument } from './ssr-window.esm.mjs';
2
- import { b as elementParents, q as elementStyle, e as elementChildren, a as setCSSProperty, i as elementOuterSize, r as elementNextAll, t as elementPrevAll, k as getTranslate, u as animateCSSModeScroll, n as nextTick, v as showWarning, c as createElement, w as elementIsChildOf, f as now, x as extend, h as elementIndex, y as deleteProps } from './utils.mjs';
2
+ import { b as elementParents, q as elementStyle, e as elementChildren, a as setCSSProperty, i as elementOuterSize, r as computeAutoSlideSize, t as elementNextAll, u as elementPrevAll, k as getTranslate, v as animateCSSModeScroll, n as nextTick, w as showWarning, c as createElement, x as elementIsChildOf, f as now, y as extend, h as elementIndex, z as deleteProps } from './utils.mjs';
3
3
 
4
4
  let support;
5
5
  function calcSupport() {
@@ -382,9 +382,6 @@ function updateSize() {
382
382
 
383
383
  function updateSlides() {
384
384
  const swiper = this;
385
- function getDirectionPropertyValue(node, label) {
386
- return parseFloat(node.getPropertyValue(swiper.getDirectionLabel(label)) || 0);
387
- }
388
385
  const params = swiper.params;
389
386
  const {
390
387
  wrapperEl,
@@ -393,10 +390,8 @@ function updateSlides() {
393
390
  rtlTranslate: rtl,
394
391
  wrongRTL
395
392
  } = swiper;
396
- const isVirtual = swiper.virtual && params.virtual.enabled;
397
- const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
398
393
  const slides = elementChildren(slidesEl, `.${swiper.params.slideClass}, swiper-slide`);
399
- const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
394
+ const slidesLength = slides.length;
400
395
  let snapGrid = [];
401
396
  const slidesGrid = [];
402
397
  const slidesSizesGrid = [];
@@ -414,15 +409,15 @@ function updateSlides() {
414
409
  let slidePosition = -offsetBefore;
415
410
  let prevSlideSize = 0;
416
411
  let index = 0;
417
- if (typeof swiperSize === 'undefined') {
418
- return;
419
- }
412
+ if (typeof swiperSize === 'undefined') return;
420
413
  if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
421
414
  spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;
422
415
  } else if (typeof spaceBetween === 'string') {
423
416
  spaceBetween = parseFloat(spaceBetween);
424
417
  }
425
- swiper.virtualSize = -spaceBetween;
418
+
419
+ // core-lite: compute total slides size without optional modules
420
+ swiper.slidesTotalSize = -spaceBetween;
426
421
 
427
422
  // reset margins
428
423
  slides.forEach(slideEl => {
@@ -440,67 +435,90 @@ function updateSlides() {
440
435
  setCSSProperty(wrapperEl, '--swiper-centered-offset-before', '');
441
436
  setCSSProperty(wrapperEl, '--swiper-centered-offset-after', '');
442
437
  }
443
- const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;
444
- if (gridEnabled) {
445
- swiper.grid.initSlides(slides);
446
- } else if (swiper.grid) {
447
- swiper.grid.unsetSlides();
448
- }
449
438
 
450
439
  // Calc slides
451
440
  let slideSize;
452
- const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {
453
- return typeof params.breakpoints[key].slidesPerView !== 'undefined';
454
- }).length > 0;
455
- for (let i = 0; i < slidesLength; i += 1) {
456
- slideSize = 0;
457
- let slide;
458
- if (slides[i]) slide = slides[i];
459
- if (gridEnabled) {
460
- swiper.grid.updateSlide(i, slide, slides);
461
- }
462
- if (slides[i] && elementStyle(slide, 'display') === 'none') continue; // eslint-disable-line
441
+ const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => typeof params.breakpoints[key].slidesPerView !== 'undefined').length > 0;
442
+ const isAutoSlidesPerView = params.slidesPerView === 'auto';
463
443
 
464
- if (params.slidesPerView === 'auto') {
444
+ // --- Phase 1: Batch DOM writes (grid updates, width/transform resets) ---
445
+ // Moving all style writes before any reads prevents per-slide forced reflows
446
+
447
+ const savedTransforms = [];
448
+ if (isAutoSlidesPerView) {
449
+ for (let i = 0; i < slidesLength; i += 1) {
450
+ if (!slides[i]) continue;
465
451
  if (shouldResetSlideSize) {
466
452
  slides[i].style[swiper.getDirectionLabel('width')] = ``;
467
453
  }
468
- const slideStyles = getComputedStyle(slide);
469
- const currentTransform = slide.style.transform;
470
- const currentWebKitTransform = slide.style.webkitTransform;
454
+ const currentTransform = slides[i].style.transform;
455
+ const currentWebKitTransform = slides[i].style.webkitTransform;
456
+ savedTransforms[i] = {
457
+ transform: currentTransform,
458
+ webkitTransform: currentWebKitTransform
459
+ };
471
460
  if (currentTransform) {
472
- slide.style.transform = 'none';
461
+ slides[i].style.transform = 'none';
473
462
  }
474
463
  if (currentWebKitTransform) {
475
- slide.style.webkitTransform = 'none';
464
+ slides[i].style.webkitTransform = 'none';
476
465
  }
466
+ }
467
+ }
468
+
469
+ // --- Phase 2: Batch DOM reads (single forced reflow for all slides) ---
470
+ // Read wrapper offset here (before Phase 3 writes) so it's batched with slide reads, not after
471
+ const wrapperOffset = swiper.isElement ? swiper.wrapperEl[`offset${swiper.isHorizontal() ? 'Left' : 'Top'}`] : 0;
472
+ const slideVisible = [];
473
+ const slideSizes = [];
474
+ for (let i = 0; i < slidesLength; i += 1) {
475
+ if (!slides[i]) {
476
+ slideVisible[i] = false;
477
+ continue;
478
+ }
479
+ if (elementStyle(slides[i], 'display') === 'none') {
480
+ slideVisible[i] = false;
481
+ continue;
482
+ }
483
+ slideVisible[i] = true;
484
+
485
+ // Cache offsetHeight for autoHeight (batched here to avoid a separate forced reflow in updateAutoHeight)
486
+ if (params.autoHeight) {
487
+ slides[i].swiperSlideHeight = slides[i]['offsetHeight'];
488
+ }
489
+ if (isAutoSlidesPerView) {
477
490
  if (params.roundLengths) {
478
- slideSize = swiper.isHorizontal() ? elementOuterSize(slide, 'width', true) : elementOuterSize(slide, 'height', true);
491
+ slideSizes[i] = swiper.isHorizontal() ? elementOuterSize(slides[i], 'width', true) : elementOuterSize(slides[i], 'height', true);
479
492
  } else {
480
- // eslint-disable-next-line
481
- const width = getDirectionPropertyValue(slideStyles, 'width');
482
- const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');
483
- const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');
484
- const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');
485
- const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');
486
- const boxSizing = slideStyles.getPropertyValue('box-sizing');
487
- if (boxSizing && boxSizing === 'border-box') {
488
- slideSize = width + marginLeft + marginRight;
489
- } else {
490
- const {
491
- clientWidth,
492
- offsetWidth
493
- } = slide;
494
- slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);
495
- }
493
+ slideSizes[i] = computeAutoSlideSize({
494
+ el: slides[i],
495
+ swiper
496
+ });
496
497
  }
497
- if (currentTransform) {
498
- slide.style.transform = currentTransform;
498
+ if (params.roundLengths) slideSizes[i] = Math.floor(slideSizes[i]);
499
+ }
500
+ }
501
+
502
+ // --- Phase 3: Restore transforms (batch write) ---
503
+ if (isAutoSlidesPerView) {
504
+ for (let i = 0; i < slidesLength; i += 1) {
505
+ if (!savedTransforms[i]) continue;
506
+ if (savedTransforms[i].transform) {
507
+ slides[i].style.transform = savedTransforms[i].transform;
499
508
  }
500
- if (currentWebKitTransform) {
501
- slide.style.webkitTransform = currentWebKitTransform;
509
+ if (savedTransforms[i].webkitTransform) {
510
+ slides[i].style.webkitTransform = savedTransforms[i].webkitTransform;
502
511
  }
503
- if (params.roundLengths) slideSize = Math.floor(slideSize);
512
+ }
513
+ }
514
+
515
+ // --- Phase 4: Calculate positions + set sizes (math + deferred writes) ---
516
+ const cssOverflowAdj = swiper.cssOverflowAdjustment();
517
+ for (let i = 0; i < slidesLength; i += 1) {
518
+ slideSize = 0;
519
+ if (!slideVisible[i]) continue;
520
+ if (isAutoSlidesPerView) {
521
+ slideSize = slideSizes[i] || 0;
504
522
  } else {
505
523
  slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;
506
524
  if (params.roundLengths) slideSize = Math.floor(slideSize);
@@ -508,13 +526,13 @@ function updateSlides() {
508
526
  slides[i].style[swiper.getDirectionLabel('width')] = `${slideSize}px`;
509
527
  }
510
528
  }
511
- if (slides[i]) {
512
- slides[i].swiperSlideSize = slideSize;
513
- }
529
+ if (slides[i]) slides[i].swiperSlideSize = slideSize;
514
530
  slidesSizesGrid.push(slideSize);
515
531
  if (params.centeredSlides) {
516
532
  slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
517
- if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
533
+ if (prevSlideSize === 0 && i !== 0) {
534
+ slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
535
+ }
518
536
  if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
519
537
  if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
520
538
  if (params.roundLengths) slidePosition = Math.floor(slidePosition);
@@ -522,55 +540,42 @@ function updateSlides() {
522
540
  slidesGrid.push(slidePosition);
523
541
  } else {
524
542
  if (params.roundLengths) slidePosition = Math.floor(slidePosition);
525
- if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);
543
+ if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) {
544
+ snapGrid.push(slidePosition);
545
+ }
526
546
  slidesGrid.push(slidePosition);
527
547
  slidePosition = slidePosition + slideSize + spaceBetween;
528
548
  }
529
- swiper.virtualSize += slideSize + spaceBetween;
549
+
550
+ // Set swiperSlideOffset from computed grid position (avoids DOM reads in updateSlidesOffset)
551
+ if (slides[i]) {
552
+ slides[i].swiperSlideOffset = slidesGrid[slidesGrid.length - 1] - cssOverflowAdj - wrapperOffset;
553
+ }
554
+ swiper.slidesTotalSize += slideSize + spaceBetween;
530
555
  prevSlideSize = slideSize;
531
556
  index += 1;
532
557
  }
533
- swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
534
- if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
535
- wrapperEl.style.width = `${swiper.virtualSize + spaceBetween}px`;
558
+ swiper.slidesTotalSize = Math.max(swiper.slidesTotalSize, swiperSize) + offsetAfter;
559
+ if (rtl && wrongRTL && params.effect === 'slide') {
560
+ wrapperEl.style.width = `${swiper.slidesTotalSize + spaceBetween}px`;
536
561
  }
537
562
  if (params.setWrapperSize) {
538
- wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`;
539
- }
540
- if (gridEnabled) {
541
- swiper.grid.updateWrapperSize(slideSize, snapGrid);
563
+ wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.slidesTotalSize + spaceBetween}px`;
542
564
  }
543
565
 
544
- // Remove last grid elements depending on width
566
+ // Remove last snap points depending on width (non-centered)
545
567
  if (!params.centeredSlides) {
546
568
  const newSlidesGrid = [];
547
569
  for (let i = 0; i < snapGrid.length; i += 1) {
548
570
  let slidesGridItem = snapGrid[i];
549
571
  if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
550
- if (snapGrid[i] <= swiper.virtualSize - swiperSize) {
572
+ if (snapGrid[i] <= swiper.slidesTotalSize - swiperSize) {
551
573
  newSlidesGrid.push(slidesGridItem);
552
574
  }
553
575
  }
554
576
  snapGrid = newSlidesGrid;
555
- if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
556
- snapGrid.push(swiper.virtualSize - swiperSize);
557
- }
558
- }
559
- if (isVirtual && params.loop) {
560
- const size = slidesSizesGrid[0] + spaceBetween;
561
- if (params.slidesPerGroup > 1) {
562
- const groups = Math.ceil((swiper.virtual.slidesBefore + swiper.virtual.slidesAfter) / params.slidesPerGroup);
563
- const groupSize = size * params.slidesPerGroup;
564
- for (let i = 0; i < groups; i += 1) {
565
- snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize);
566
- }
567
- }
568
- for (let i = 0; i < swiper.virtual.slidesBefore + swiper.virtual.slidesAfter; i += 1) {
569
- if (params.slidesPerGroup === 1) {
570
- snapGrid.push(snapGrid[snapGrid.length - 1] + size);
571
- }
572
- slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size);
573
- swiper.virtualSize += size;
577
+ if (Math.floor(swiper.slidesTotalSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
578
+ snapGrid.push(swiper.slidesTotalSize - swiperSize);
574
579
  }
575
580
  }
576
581
  if (snapGrid.length === 0) snapGrid = [0];
@@ -578,9 +583,7 @@ function updateSlides() {
578
583
  const key = swiper.isHorizontal() && rtl ? 'marginLeft' : swiper.getDirectionLabel('marginRight');
579
584
  slides.filter((_, slideIndex) => {
580
585
  if (!params.cssMode || params.loop) return true;
581
- if (slideIndex === slides.length - 1) {
582
- return false;
583
- }
586
+ if (slideIndex === slides.length - 1) return false;
584
587
  return true;
585
588
  }).forEach(slideEl => {
586
589
  slideEl.style[key] = `${spaceBetween}px`;
@@ -630,7 +633,9 @@ function updateSlides() {
630
633
  swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);
631
634
  swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);
632
635
  }
633
- if (slidesLength !== previousSlidesLength) {
636
+
637
+ // Emit changes
638
+ if (slidesLength !== slides.length) {
634
639
  swiper.emit('slidesLengthChange');
635
640
  }
636
641
  if (snapGrid.length !== previousSnapGridLength) {
@@ -641,10 +646,12 @@ function updateSlides() {
641
646
  swiper.emit('slidesGridLengthChange');
642
647
  }
643
648
  if (params.watchSlidesProgress) {
644
- swiper.updateSlidesOffset();
649
+ swiper.updateSlidesOffset({
650
+ isCalculatedFromUpdateSlides: true
651
+ });
645
652
  }
646
653
  swiper.emit('slidesUpdated');
647
- if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) {
654
+ if (!params.cssMode && params.effect === 'slide') {
648
655
  const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`;
649
656
  const hasClassBackfaceClassAdded = swiper.el.classList.contains(backFaceHiddenClass);
650
657
  if (slidesLength <= params.maxBackfaceHiddenSlides) {
@@ -658,20 +665,13 @@ function updateSlides() {
658
665
  function updateAutoHeight(speed) {
659
666
  const swiper = this;
660
667
  const activeSlides = [];
661
- const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
662
- let newHeight = 0;
663
- let i;
664
668
  if (typeof speed === 'number') {
665
669
  swiper.setTransition(speed);
666
670
  } else if (speed === true) {
667
671
  swiper.setTransition(swiper.params.speed);
668
672
  }
669
- const getSlideByIndex = index => {
670
- if (isVirtual) {
671
- return swiper.slides[swiper.getSlideIndexByData(index)];
672
- }
673
- return swiper.slides[index];
674
- };
673
+ const getSlideByIndex = index => swiper.slides[index];
674
+
675
675
  // Find slides currently in view
676
676
  if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
677
677
  if (swiper.params.centeredSlides) {
@@ -679,9 +679,9 @@ function updateAutoHeight(speed) {
679
679
  activeSlides.push(slide);
680
680
  });
681
681
  } else {
682
- for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
682
+ for (let i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
683
683
  const index = swiper.activeIndex + i;
684
- if (index > swiper.slides.length && !isVirtual) break;
684
+ if (index > swiper.slides.length) break;
685
685
  activeSlides.push(getSlideByIndex(index));
686
686
  }
687
687
  }
@@ -690,18 +690,23 @@ function updateAutoHeight(speed) {
690
690
  }
691
691
 
692
692
  // Find new height from highest slide in view
693
- for (i = 0; i < activeSlides.length; i += 1) {
693
+ let newHeight = 0;
694
+ for (let i = 0; i < activeSlides.length; i += 1) {
694
695
  if (typeof activeSlides[i] !== 'undefined') {
695
- const height = activeSlides[i].offsetHeight;
696
+ const height = activeSlides[i].swiperSlideHeight ?? activeSlides[i]['offsetHeight'];
696
697
  newHeight = height > newHeight ? height : newHeight;
697
698
  }
698
699
  }
699
-
700
- // Update Height
701
700
  if (newHeight || newHeight === 0) swiper.wrapperEl.style.height = `${newHeight}px`;
702
701
  }
703
702
 
704
- function updateSlidesOffset() {
703
+ function updateSlidesOffset(params) {
704
+ const {
705
+ isCalculatedFromUpdateSlides = false
706
+ } = params ?? {};
707
+ if (isCalculatedFromUpdateSlides) {
708
+ return;
709
+ }
705
710
  const swiper = this;
706
711
  const slides = swiper.slides;
707
712
  // eslint-disable-next-line
@@ -842,46 +847,16 @@ function updateSlidesClasses() {
842
847
  slidesEl,
843
848
  activeIndex
844
849
  } = swiper;
845
- const isVirtual = swiper.virtual && params.virtual.enabled;
846
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
847
- const getFilteredSlide = selector => {
848
- return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
849
- };
850
- let activeSlide;
851
- let prevSlide;
850
+ const getNextSlide = slideEl => elementNextAll(slideEl, `.${params.slideClass}, swiper-slide`)[0];
851
+ const getPrevSlide = slideEl => elementPrevAll(slideEl, `.${params.slideClass}, swiper-slide`)[0];
852
+ const activeSlide = slides[activeIndex];
852
853
  let nextSlide;
853
- if (isVirtual) {
854
- if (params.loop) {
855
- let slideIndex = activeIndex - swiper.virtual.slidesBefore;
856
- if (slideIndex < 0) slideIndex = swiper.virtual.slides.length + slideIndex;
857
- if (slideIndex >= swiper.virtual.slides.length) slideIndex -= swiper.virtual.slides.length;
858
- activeSlide = getFilteredSlide(`[data-swiper-slide-index="${slideIndex}"]`);
859
- } else {
860
- activeSlide = getFilteredSlide(`[data-swiper-slide-index="${activeIndex}"]`);
861
- }
862
- } else {
863
- if (gridEnabled) {
864
- activeSlide = slides.find(slideEl => slideEl.column === activeIndex);
865
- nextSlide = slides.find(slideEl => slideEl.column === activeIndex + 1);
866
- prevSlide = slides.find(slideEl => slideEl.column === activeIndex - 1);
867
- } else {
868
- activeSlide = slides[activeIndex];
869
- }
870
- }
854
+ let prevSlide;
871
855
  if (activeSlide) {
872
- if (!gridEnabled) {
873
- // Next Slide
874
- nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
875
- if (params.loop && !nextSlide) {
876
- nextSlide = slides[0];
877
- }
878
-
879
- // Prev Slide
880
- prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
881
- if (params.loop && !prevSlide === 0) {
882
- prevSlide = slides[slides.length - 1];
883
- }
884
- }
856
+ nextSlide = getNextSlide(activeSlide);
857
+ prevSlide = getPrevSlide(activeSlide);
858
+ if (params.loop && !nextSlide) nextSlide = slides[0];
859
+ if (params.loop && !prevSlide) prevSlide = slides[slides.length - 1];
885
860
  }
886
861
  slides.forEach(slideEl => {
887
862
  toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass);
@@ -972,7 +947,6 @@ function getActiveIndexByTranslate(swiper) {
972
947
  activeIndex = i;
973
948
  }
974
949
  }
975
- // Normalize slideIndex
976
950
  if (params.normalizeSlideIndex) {
977
951
  if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;
978
952
  }
@@ -990,16 +964,6 @@ function updateActiveIndex(newActiveIndex) {
990
964
  } = swiper;
991
965
  let activeIndex = newActiveIndex;
992
966
  let snapIndex;
993
- const getVirtualRealIndex = aIndex => {
994
- let realIndex = aIndex - swiper.virtual.slidesBefore;
995
- if (realIndex < 0) {
996
- realIndex = swiper.virtual.slides.length + realIndex;
997
- }
998
- if (realIndex >= swiper.virtual.slides.length) {
999
- realIndex -= swiper.virtual.slides.length;
1000
- }
1001
- return realIndex;
1002
- };
1003
967
  if (typeof activeIndex === 'undefined') {
1004
968
  activeIndex = getActiveIndexByTranslate(swiper);
1005
969
  }
@@ -1017,32 +981,12 @@ function updateActiveIndex(newActiveIndex) {
1017
981
  }
1018
982
  return;
1019
983
  }
1020
- if (activeIndex === previousIndex && swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) {
1021
- swiper.realIndex = getVirtualRealIndex(activeIndex);
1022
- return;
1023
- }
1024
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
1025
-
1026
- // Get real index
1027
- let realIndex;
1028
- if (swiper.virtual && params.virtual.enabled && params.loop) {
1029
- realIndex = getVirtualRealIndex(activeIndex);
1030
- } else if (gridEnabled) {
1031
- const firstSlideInColumn = swiper.slides.find(slideEl => slideEl.column === activeIndex);
1032
- let activeSlideIndex = parseInt(firstSlideInColumn.getAttribute('data-swiper-slide-index'), 10);
1033
- if (Number.isNaN(activeSlideIndex)) {
1034
- activeSlideIndex = Math.max(swiper.slides.indexOf(firstSlideInColumn), 0);
1035
- }
1036
- realIndex = Math.floor(activeSlideIndex / params.grid.rows);
1037
- } else if (swiper.slides[activeIndex]) {
984
+ let realIndex = activeIndex;
985
+ if (swiper.slides[activeIndex]) {
1038
986
  const slideIndex = swiper.slides[activeIndex].getAttribute('data-swiper-slide-index');
1039
987
  if (slideIndex) {
1040
988
  realIndex = parseInt(slideIndex, 10);
1041
- } else {
1042
- realIndex = activeIndex;
1043
989
  }
1044
- } else {
1045
- realIndex = activeIndex;
1046
990
  }
1047
991
  Object.assign(swiper, {
1048
992
  previousSnapIndex,
@@ -1089,11 +1033,7 @@ function updateClickedSlide(el, path) {
1089
1033
  }
1090
1034
  if (slide && slideFound) {
1091
1035
  swiper.clickedSlide = slide;
1092
- if (swiper.virtual && swiper.params.virtual.enabled) {
1093
- swiper.clickedIndex = parseInt(slide.getAttribute('data-swiper-slide-index'), 10);
1094
- } else {
1095
- swiper.clickedIndex = slideIndex;
1096
- }
1036
+ swiper.clickedIndex = slideIndex;
1097
1037
  } else {
1098
1038
  swiper.clickedSlide = undefined;
1099
1039
  swiper.clickedIndex = undefined;
@@ -1127,9 +1067,6 @@ function getSwiperTranslate(axis) {
1127
1067
  translate,
1128
1068
  wrapperEl
1129
1069
  } = swiper;
1130
- if (params.virtualTranslate) {
1131
- return rtl ? -translate : translate;
1132
- }
1133
1070
  if (params.cssMode) {
1134
1071
  return translate;
1135
1072
  }
@@ -1163,7 +1100,7 @@ function setTranslate(translate, byController) {
1163
1100
  swiper.translate = swiper.isHorizontal() ? x : y;
1164
1101
  if (params.cssMode) {
1165
1102
  wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;
1166
- } else if (!params.virtualTranslate) {
1103
+ } else {
1167
1104
  if (swiper.isHorizontal()) {
1168
1105
  x -= swiper.cssOverflowAdjustment();
1169
1106
  } else {
@@ -1400,7 +1337,6 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
1400
1337
  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
1401
1338
  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
1402
1339
  const translate = -snapGrid[snapIndex];
1403
- // Normalize slideIndex
1404
1340
  if (params.normalizeSlideIndex) {
1405
1341
  for (let i = 0; i < slidesGrid.length; i += 1) {
1406
1342
  const normalizedTranslate = -Math.floor(translate * 100);
@@ -1417,33 +1353,24 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
1417
1353
  }
1418
1354
  }
1419
1355
  }
1356
+
1420
1357
  // Directions locks
1421
1358
  if (swiper.initialized && slideIndex !== activeIndex) {
1422
1359
  if (!swiper.allowSlideNext && (rtl ? translate > swiper.translate && translate > swiper.minTranslate() : translate < swiper.translate && translate < swiper.minTranslate())) {
1423
1360
  return false;
1424
1361
  }
1425
1362
  if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
1426
- if ((activeIndex || 0) !== slideIndex) {
1427
- return false;
1428
- }
1363
+ if ((activeIndex || 0) !== slideIndex) return false;
1429
1364
  }
1430
1365
  }
1431
1366
  if (slideIndex !== (previousIndex || 0) && runCallbacks) {
1432
1367
  swiper.emit('beforeSlideChangeStart');
1433
1368
  }
1434
-
1435
- // Update progress
1436
1369
  swiper.updateProgress(translate);
1437
1370
  let direction;
1438
1371
  if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset';
1439
-
1440
- // initial virtual
1441
- const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
1442
- const isInitialVirtual = isVirtual && initial;
1443
- // Update Index
1444
- if (!isInitialVirtual && (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate)) {
1372
+ if (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate) {
1445
1373
  swiper.updateActiveIndex(slideIndex);
1446
- // Update Height
1447
1374
  if (params.autoHeight) {
1448
1375
  swiper.updateAutoHeight();
1449
1376
  }
@@ -1461,24 +1388,7 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
1461
1388
  const isH = swiper.isHorizontal();
1462
1389
  const t = rtl ? translate : -translate;
1463
1390
  if (speed === 0) {
1464
- if (isVirtual) {
1465
- swiper.wrapperEl.style.scrollSnapType = 'none';
1466
- swiper._immediateVirtual = true;
1467
- }
1468
- if (isVirtual && !swiper._cssModeVirtualInitialSet && swiper.params.initialSlide > 0) {
1469
- swiper._cssModeVirtualInitialSet = true;
1470
- requestAnimationFrame(() => {
1471
- wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
1472
- });
1473
- } else {
1474
- wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
1475
- }
1476
- if (isVirtual) {
1477
- requestAnimationFrame(() => {
1478
- swiper.wrapperEl.style.scrollSnapType = '';
1479
- swiper._immediateVirtual = false;
1480
- });
1481
- }
1391
+ wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
1482
1392
  } else {
1483
1393
  if (!swiper.support.smoothScroll) {
1484
1394
  animateCSSModeScroll({
@@ -1496,10 +1406,7 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
1496
1406
  return true;
1497
1407
  }
1498
1408
  const browser = getBrowser();
1499
- const isSafari = browser.isSafari;
1500
- if (isVirtual && !initial && isSafari && swiper.isElement) {
1501
- swiper.virtual.update(false, false, slideIndex);
1502
- }
1409
+ browser.isSafari;
1503
1410
  swiper.setTransition(speed);
1504
1411
  swiper.setTranslate(translate);
1505
1412
  swiper.updateActiveIndex(slideIndex);
@@ -1670,8 +1577,6 @@ function slideToLoopCenterSneakPeek(index, speed, runCallbacks, internal) {
1670
1577
  if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
1671
1578
  const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
1672
1579
  const swiperTranslate = JSON.parse(JSON.stringify(swiper.snapGrid[1]));
1673
-
1674
- // Move last item to first position only if active slide is the first slide
1675
1580
  const lastSlide = slides[slides.length - 1];
1676
1581
  lastSlide.swiperLoopMoveDOM = true;
1677
1582
  swiper.slidesEl.prepend(lastSlide);
@@ -1706,11 +1611,8 @@ function slideNext(speed, runCallbacks, internal) {
1706
1611
  perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
1707
1612
  }
1708
1613
  const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup;
1709
- const isVirtual = swiper.virtual && params.virtual.enabled;
1710
1614
  if (params.loop) {
1711
- if (animating && !isVirtual && params.loopPreventsSliding) return false;
1712
-
1713
- // Kiểm tra xem loop có bị disable không
1615
+ if (animating && params.loopPreventsSliding) return false;
1714
1616
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
1715
1617
  if (swiper.slides.length >= currentSlidesPerView) {
1716
1618
  swiper.loopFix({
@@ -1737,7 +1639,6 @@ function slideNext(speed, runCallbacks, internal) {
1737
1639
  const gap = Math.abs(swiper.snapGrid[lastSnapGridIndex] - swiper.snapGrid[lastSnapGridIndex - 1]);
1738
1640
  const swiperTranslate = structuredClone(swiper.snapGrid[lastSnapGridIndex - 1]);
1739
1641
  if (!swiper.params.loop) return;
1740
- // Move first item to last position only if active slide is the last slide
1741
1642
  const firstSlide = slides[0];
1742
1643
  firstSlide.swiperLoopMoveDOM = true;
1743
1644
  swiper.slidesEl.append(firstSlide);
@@ -1762,17 +1663,14 @@ function slidePrev(speed, runCallbacks, internal) {
1762
1663
  params,
1763
1664
  snapGrid,
1764
1665
  slidesGrid,
1765
- rtlTranslate,
1766
- enabled,
1767
- animating
1666
+ rtlTranslate: rtlTranslate,
1667
+ enabled
1768
1668
  } = swiper;
1769
1669
  if (!enabled || swiper.destroyed) return swiper;
1770
1670
  if (typeof speed === 'undefined') {
1771
1671
  speed = swiper.params.speed;
1772
1672
  }
1773
- swiper.virtual && params.virtual.enabled;
1774
1673
  if (params.loop) {
1775
- // Kiểm tra xem loop có bị disable không
1776
1674
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
1777
1675
  if (swiper.slides.length >= currentSlidesPerView) {
1778
1676
  swiper.loopFix({
@@ -1789,18 +1687,16 @@ function slidePrev(speed, runCallbacks, internal) {
1789
1687
  }
1790
1688
  const normalizedTranslate = normalize(translate);
1791
1689
  const normalizedSnapGrid = snapGrid.map(val => normalize(val));
1792
- const isFreeMode = params.freeMode && params.freeMode.enabled;
1793
1690
  let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
1794
- if (typeof prevSnap === 'undefined' && (params.cssMode || isFreeMode)) {
1691
+ if (typeof prevSnap === 'undefined' && params.cssMode) {
1795
1692
  let prevSnapIndex;
1796
1693
  snapGrid.forEach((snap, snapIndex) => {
1797
1694
  if (normalizedTranslate >= snap) {
1798
- // prevSnap = snap;
1799
1695
  prevSnapIndex = snapIndex;
1800
1696
  }
1801
1697
  });
1802
1698
  if (typeof prevSnapIndex !== 'undefined') {
1803
- prevSnap = isFreeMode ? snapGrid[prevSnapIndex] : snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];
1699
+ prevSnap = snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];
1804
1700
  }
1805
1701
  }
1806
1702
  let prevIndex = 0;
@@ -1813,7 +1709,7 @@ function slidePrev(speed, runCallbacks, internal) {
1813
1709
  }
1814
1710
  }
1815
1711
  if (params.rewind && swiper.isBeginning) {
1816
- const lastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;
1712
+ const lastIndex = swiper.slides.length - 1;
1817
1713
  return swiper.slideTo(lastIndex, speed, runCallbacks, internal);
1818
1714
  } else if (params.loop && swiper.activeIndex === 0 && params.cssMode) {
1819
1715
  requestAnimationFrame(() => {
@@ -1827,8 +1723,6 @@ function slidePrev(speed, runCallbacks, internal) {
1827
1723
  if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
1828
1724
  const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
1829
1725
  const swiperTranslate = JSON.parse(JSON.stringify(swiper.snapGrid[1]));
1830
-
1831
- // Move last item to first position only if active slide is the first slide
1832
1726
  if (!swiper.params.loop) return;
1833
1727
  const lastSlide = slides[slides.length - 1];
1834
1728
  lastSlide.swiperLoopMoveDOM = true;
@@ -1905,20 +1799,19 @@ function slideToClickedSlide() {
1905
1799
  slidesEl
1906
1800
  } = swiper;
1907
1801
  const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
1908
- let slideToIndex = swiper.getSlideIndexWhenGrid(swiper.clickedIndex);
1802
+ const slideToIndex = swiper.clickedIndex;
1909
1803
  let realIndex;
1910
1804
  const slideSelector = swiper.isElement ? `swiper-slide` : `.${params.slideClass}`;
1911
- const isGrid = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
1912
1805
  if (params.loop) {
1913
1806
  if (swiper.animating) return;
1914
1807
  realIndex = parseInt(swiper.clickedSlide.getAttribute('data-swiper-slide-index'), 10);
1915
1808
  if (params.centeredSlides) {
1916
1809
  swiper.slideToLoop(realIndex);
1917
- } else if (slideToIndex > (isGrid ? (swiper.slides.length - slidesPerView) / 2 - (swiper.params.grid.rows - 1) : swiper.slides.length - slidesPerView)) {
1810
+ } else if (slideToIndex > swiper.slides.length - slidesPerView) {
1918
1811
  swiper.loopFix();
1919
- slideToIndex = swiper.getSlideIndex(elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0]);
1812
+ const clickedEl = elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0];
1920
1813
  nextTick(() => {
1921
- swiper.slideTo(slideToIndex);
1814
+ if (clickedEl) swiper.slideTo(swiper.getSlideIndex(clickedEl));
1922
1815
  });
1923
1816
  } else {
1924
1817
  swiper.slideTo(slideToIndex);
@@ -1945,7 +1838,7 @@ function loopCreate(slideRealIndex, initial) {
1945
1838
  params,
1946
1839
  slidesEl
1947
1840
  } = swiper;
1948
- if (!params.loop || swiper.virtual && swiper.params.virtual.enabled) return;
1841
+ if (!params.loop) return;
1949
1842
  const initSlides = () => {
1950
1843
  const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`);
1951
1844
  slides.forEach((el, index) => {
@@ -1954,21 +1847,17 @@ function loopCreate(slideRealIndex, initial) {
1954
1847
  };
1955
1848
  const clearBlankSlides = () => {
1956
1849
  const slides = elementChildren(slidesEl, `.${params.slideBlankClass}`);
1957
- slides.forEach(el => {
1958
- el.remove();
1959
- });
1850
+ slides.forEach(el => el.remove());
1960
1851
  if (slides.length > 0) {
1961
1852
  swiper.recalcSlides();
1962
1853
  swiper.updateSlides();
1963
1854
  }
1964
1855
  };
1965
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
1966
- if (params.loopAddBlankSlides && (params.slidesPerGroup > 1 || gridEnabled)) {
1856
+ if (params.loopAddBlankSlides && params.slidesPerGroup > 1) {
1967
1857
  clearBlankSlides();
1968
1858
  }
1969
- const slidesPerGroup = params.slidesPerGroup * (gridEnabled ? params.grid.rows : 1);
1859
+ const slidesPerGroup = params.slidesPerGroup;
1970
1860
  const shouldFillGroup = swiper.slides.length % slidesPerGroup !== 0;
1971
- const shouldFillGrid = gridEnabled && swiper.slides.length % params.grid.rows !== 0;
1972
1861
  const addBlankSlides = amountOfSlides => {
1973
1862
  for (let i = 0; i < amountOfSlides; i += 1) {
1974
1863
  const slideEl = swiper.isElement ? createElement('swiper-slide', [params.slideBlankClass]) : createElement('div', [params.slideClass, params.slideBlankClass]);
@@ -1985,16 +1874,6 @@ function loopCreate(slideRealIndex, initial) {
1985
1874
  showWarning('Swiper Loop Warning: The number of slides is not even to slidesPerGroup, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)');
1986
1875
  }
1987
1876
  initSlides();
1988
- } else if (shouldFillGrid) {
1989
- if (params.loopAddBlankSlides) {
1990
- const slidesToAdd = params.grid.rows - swiper.slides.length % params.grid.rows;
1991
- addBlankSlides(slidesToAdd);
1992
- swiper.recalcSlides();
1993
- swiper.updateSlides();
1994
- } else {
1995
- showWarning('Swiper Loop Warning: The number of slides is not even to grid.rows, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)');
1996
- }
1997
- initSlides();
1998
1877
  } else {
1999
1878
  initSlides();
2000
1879
  }
@@ -2013,13 +1892,12 @@ function loopFix(_temp) {
2013
1892
  setTranslate,
2014
1893
  activeSlideIndex,
2015
1894
  initial,
2016
- byController,
2017
1895
  byMousewheel
2018
1896
  } = _temp === void 0 ? {} : _temp;
2019
1897
  const swiper = this;
2020
1898
  if (!swiper.params.loop) return;
2021
1899
 
2022
- // Disable loop mode nếu số slides ít hơn slidesPerView
1900
+ // Disable loop mode if number of slides is smaller than slidesPerView
2023
1901
  const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2024
1902
  if (swiper.slides.length < currentSlidesPerView) {
2025
1903
  console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
@@ -2039,21 +1917,6 @@ function loopFix(_temp) {
2039
1917
  } = params;
2040
1918
  swiper.allowSlidePrev = true;
2041
1919
  swiper.allowSlideNext = true;
2042
- if (swiper.virtual && params.virtual.enabled) {
2043
- if (slideTo) {
2044
- if (!params.centeredSlides && swiper.snapIndex === 0) {
2045
- swiper.slideTo(swiper.virtual.slides.length, 0, false, true);
2046
- } else if (params.centeredSlides && swiper.snapIndex < params.slidesPerView) {
2047
- swiper.slideTo(swiper.virtual.slides.length + swiper.snapIndex, 0, false, true);
2048
- } else if (swiper.snapIndex === swiper.snapGrid.length - 1) {
2049
- swiper.slideTo(swiper.virtual.slidesBefore, 0, false, true);
2050
- }
2051
- }
2052
- swiper.allowSlidePrev = allowSlidePrev;
2053
- swiper.allowSlideNext = allowSlideNext;
2054
- swiper.emit('loopFix');
2055
- return;
2056
- }
2057
1920
  let slidesPerView = params.slidesPerView;
2058
1921
  if (slidesPerView === 'auto') {
2059
1922
  slidesPerView = swiper.slidesPerViewDynamic();
@@ -2063,22 +1926,19 @@ function loopFix(_temp) {
2063
1926
  slidesPerView = slidesPerView + 1;
2064
1927
  }
2065
1928
  }
2066
- const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup;
1929
+ const slidesPerGroup = params.slidesPerGroup;
2067
1930
  let loopedSlides = centeredSlides ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) : slidesPerGroup;
2068
1931
  if (loopedSlides % slidesPerGroup !== 0) {
2069
1932
  loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup;
2070
1933
  }
2071
1934
  loopedSlides += params.loopAdditionalSlides;
2072
1935
  swiper.loopedSlides = loopedSlides;
2073
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
2074
- if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
1936
+ if (slides.length < slidesPerView + loopedSlides) {
2075
1937
  showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
2076
- } else if (gridEnabled && params.grid.fill === 'row') {
2077
- showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
2078
1938
  }
2079
1939
  const prependSlidesIndexes = [];
2080
1940
  const appendSlidesIndexes = [];
2081
- const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length;
1941
+ const cols = slides.length;
2082
1942
  const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !centeredSlides;
2083
1943
  let activeIndex = isInitialOverflow ? initialSlide : swiper.activeIndex;
2084
1944
  if (typeof activeSlideIndex === 'undefined') {
@@ -2090,24 +1950,15 @@ function loopFix(_temp) {
2090
1950
  const isPrev = direction === 'prev' || !direction;
2091
1951
  let slidesPrepended = 0;
2092
1952
  let slidesAppended = 0;
2093
- const activeColIndex = gridEnabled ? slides[activeSlideIndex].column : activeSlideIndex;
1953
+ const activeColIndex = activeSlideIndex;
2094
1954
  const activeColIndexWithShift = activeColIndex + (centeredSlides && typeof setTranslate === 'undefined' ? -slidesPerView / 2 + 0.5 : 0);
1955
+
2095
1956
  // prepend last slides before start
2096
1957
  if (activeColIndexWithShift < loopedSlides) {
2097
1958
  slidesPrepended = Math.max(loopedSlides - activeColIndexWithShift, slidesPerGroup);
2098
1959
  for (let i = 0; i < loopedSlides - activeColIndexWithShift; i += 1) {
2099
1960
  const index = i - Math.floor(i / cols) * cols;
2100
- if (gridEnabled) {
2101
- const colIndexToPrepend = cols - index - 1;
2102
- for (let i = slides.length - 1; i >= 0; i -= 1) {
2103
- if (slides[i].column === colIndexToPrepend) prependSlidesIndexes.push(i);
2104
- }
2105
- // slides.forEach((slide, slideIndex) => {
2106
- // if (slide.column === colIndexToPrepend) prependSlidesIndexes.push(slideIndex);
2107
- // });
2108
- } else {
2109
- prependSlidesIndexes.push(cols - index - 1);
2110
- }
1961
+ prependSlidesIndexes.push(cols - index - 1);
2111
1962
  }
2112
1963
  } else if (activeColIndexWithShift + slidesPerView > cols - loopedSlides) {
2113
1964
  slidesAppended = Math.max(activeColIndexWithShift - (cols - loopedSlides * 2), slidesPerGroup);
@@ -2116,27 +1967,13 @@ function loopFix(_temp) {
2116
1967
  }
2117
1968
  for (let i = 0; i < slidesAppended; i += 1) {
2118
1969
  const index = i - Math.floor(i / cols) * cols;
2119
- if (gridEnabled) {
2120
- slides.forEach((slide, slideIndex) => {
2121
- if (slide.column === index) appendSlidesIndexes.push(slideIndex);
2122
- });
2123
- } else {
2124
- appendSlidesIndexes.push(index);
2125
- }
1970
+ appendSlidesIndexes.push(index);
2126
1971
  }
2127
1972
  }
2128
1973
  swiper.__preventObserver__ = true;
2129
1974
  requestAnimationFrame(() => {
2130
1975
  swiper.__preventObserver__ = false;
2131
1976
  });
2132
- if (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2133
- if (appendSlidesIndexes.includes(activeSlideIndex)) {
2134
- appendSlidesIndexes.splice(appendSlidesIndexes.indexOf(activeSlideIndex), 1);
2135
- }
2136
- if (prependSlidesIndexes.includes(activeSlideIndex)) {
2137
- prependSlidesIndexes.splice(prependSlidesIndexes.indexOf(activeSlideIndex), 1);
2138
- }
2139
- }
2140
1977
  if (isPrev) {
2141
1978
  prependSlidesIndexes.forEach(index => {
2142
1979
  slides[index].swiperLoopMoveDOM = true;
@@ -2154,13 +1991,11 @@ function loopFix(_temp) {
2154
1991
  swiper.recalcSlides();
2155
1992
  if (params.slidesPerView === 'auto') {
2156
1993
  swiper.updateSlides();
2157
- } else if (gridEnabled && (prependSlidesIndexes.length > 0 && isPrev || appendSlidesIndexes.length > 0 && isNext)) {
2158
- swiper.slides.forEach((slide, slideIndex) => {
2159
- swiper.grid.updateSlide(slideIndex, slide, swiper.slides);
2160
- });
2161
1994
  }
2162
1995
  if (params.watchSlidesProgress) {
2163
- swiper.updateSlidesOffset();
1996
+ swiper.updateSlidesOffset({
1997
+ isCalculatedFromUpdateSlides: params.slidesPerView === 'auto'
1998
+ });
2164
1999
  }
2165
2000
  if (slideTo) {
2166
2001
  if (prependSlidesIndexes.length > 0 && isPrev) {
@@ -2177,12 +2012,10 @@ function loopFix(_temp) {
2177
2012
  swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff;
2178
2013
  }
2179
2014
  }
2180
- } else {
2181
- if (setTranslate) {
2182
- const shift = gridEnabled ? prependSlidesIndexes.length / params.grid.rows : prependSlidesIndexes.length;
2183
- swiper.slideTo(swiper.activeIndex + shift, 0, false, true);
2184
- swiper.touchEventsData.currentTranslate = swiper.translate;
2185
- }
2015
+ } else if (setTranslate) {
2016
+ const shift = prependSlidesIndexes.length;
2017
+ swiper.slideTo(swiper.activeIndex + shift, 0, false, true);
2018
+ swiper.touchEventsData.currentTranslate = swiper.translate;
2186
2019
  }
2187
2020
  } else if (appendSlidesIndexes.length > 0 && isNext) {
2188
2021
  if (typeof slideRealIndex === 'undefined') {
@@ -2198,36 +2031,14 @@ function loopFix(_temp) {
2198
2031
  swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff;
2199
2032
  }
2200
2033
  }
2201
- } else {
2202
- const shift = gridEnabled ? appendSlidesIndexes.length / params.grid.rows : appendSlidesIndexes.length;
2034
+ } else if (setTranslate) {
2035
+ const shift = appendSlidesIndexes.length;
2203
2036
  swiper.slideTo(swiper.activeIndex - shift, 0, false, true);
2204
2037
  }
2205
2038
  }
2206
2039
  }
2207
2040
  swiper.allowSlidePrev = allowSlidePrev;
2208
2041
  swiper.allowSlideNext = allowSlideNext;
2209
- if (swiper.controller && swiper.controller.control && !byController) {
2210
- const loopParams = {
2211
- slideRealIndex,
2212
- direction,
2213
- setTranslate,
2214
- activeSlideIndex,
2215
- byController: true
2216
- };
2217
- if (Array.isArray(swiper.controller.control)) {
2218
- swiper.controller.control.forEach(c => {
2219
- if (!c.destroyed && c.params.loop) c.loopFix({
2220
- ...loopParams,
2221
- slideTo: c.params.slidesPerView === params.slidesPerView ? slideTo : false
2222
- });
2223
- });
2224
- } else if (swiper.controller.control instanceof swiper.constructor && swiper.controller.control.params.loop) {
2225
- swiper.controller.control.loopFix({
2226
- ...loopParams,
2227
- slideTo: swiper.controller.control.params.slidesPerView === params.slidesPerView ? slideTo : false
2228
- });
2229
- }
2230
- }
2231
2042
  swiper.emit('loopFix');
2232
2043
  }
2233
2044
 
@@ -2244,7 +2055,7 @@ function loopFixDot(_temp) {
2244
2055
  const swiper = this;
2245
2056
  if (!swiper.params.loop) return;
2246
2057
 
2247
- // Disable loop mode nếu số slides ít hơn slidesPerView
2058
+ // Disable loop mode if number of slides is smaller than slidesPerView
2248
2059
  const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2249
2060
  if (swiper.slides.length < currentSlidesPerView) {
2250
2061
  console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
@@ -2283,7 +2094,7 @@ function loopFixDot(_temp) {
2283
2094
  }
2284
2095
  loopedSlides += params.loopAdditionalSlides;
2285
2096
  swiper.loopedSlides = loopedSlides;
2286
- if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2097
+ if (slides.length < slidesPerView + loopedSlides) {
2287
2098
  showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
2288
2099
  }
2289
2100
  const isNext = direction === 'next' || !direction;
@@ -2309,20 +2120,16 @@ function loopFixDot(_temp) {
2309
2120
  activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass)));
2310
2121
  }
2311
2122
 
2312
- // Tạo DocumentFragment để chứa các slide clone
2123
+ // DocumentFragment to hold slide clones
2313
2124
  const cloneFragment = document.createDocumentFragment();
2314
2125
 
2315
- // Clone các slide theo numberOfSlidesNeedClone (đã đảo ngược) và thêm vào fragment
2126
+ // Clone slides according to numberOfSlidesNeedClone and append to fragment
2316
2127
  (isNext ? numberOfSlidesNeedClone : numberOfSlidesNeedClone.reverse()).forEach(index => {
2317
2128
  if (slides[index]) {
2318
2129
  const originalSlide = slides[index];
2319
2130
  const clonedSlide = originalSlide.cloneNode(true);
2320
-
2321
- // Đánh dấu slide clone
2322
2131
  clonedSlide.setAttribute('data-swiper-clone', 'true');
2323
2132
  clonedSlide.classList.add('swiper-slide-clone');
2324
-
2325
- // Thêm clone vào fragment
2326
2133
  cloneFragment.appendChild(clonedSlide);
2327
2134
  }
2328
2135
  });
@@ -2343,32 +2150,28 @@ function loopFixDot(_temp) {
2343
2150
  });
2344
2151
  }
2345
2152
 
2346
- // Sắp xếp cloneFragment theo data-swiper-slide-index tăng dần
2153
+ // Sort cloned slides by data-swiper-slide-index
2347
2154
  const clonedSlides = Array.from(cloneFragment.children);
2348
2155
  clonedSlides.sort((a, b) => {
2349
2156
  const indexA = parseInt(a.getAttribute('data-swiper-slide-index')) || 0;
2350
2157
  const indexB = parseInt(b.getAttribute('data-swiper-slide-index')) || 0;
2351
2158
  return indexA - indexB;
2352
2159
  });
2353
-
2354
- // Xóa tất cả children cũ và thêm lại theo thứ tự đã sắp xếp
2355
2160
  cloneFragment.innerHTML = '';
2356
2161
  clonedSlides.forEach(slide => {
2357
2162
  cloneFragment.appendChild(slide);
2358
2163
  });
2359
2164
 
2360
- // Thêm fragment vào vị trí phù hợp
2165
+ // Place fragment into the right position
2361
2166
  if (isPrev) {
2362
- // Nếu là prev, thêm fragment vào cuối slidesEl
2363
2167
  slidesEl.appendChild(cloneFragment);
2364
2168
  } else if (isNext) {
2365
- // Nếu là next, thêm fragment vào đầu slidesEl
2366
2169
  slidesEl.insertBefore(cloneFragment, slidesEl.firstChild);
2367
2170
  }
2368
2171
  swiper.recalcSlides();
2369
2172
  swiper.updateSlides();
2370
2173
 
2371
- // Tìm slide data-swiper-slide-index tương ứng
2174
+ // Find old active slide index after recalculation
2372
2175
  let oldActiveIndex = null;
2373
2176
  for (let i = 0; i < slidesEl.children.length; i++) {
2374
2177
  const child = slidesEl.children[i];
@@ -2381,7 +2184,7 @@ function loopFixDot(_temp) {
2381
2184
  swiper.slideTo(oldActiveIndex, 0);
2382
2185
  }
2383
2186
 
2384
- // Tìm vị trí slide sau khi remove clone để set lại translate tạo hiệu ứng animate
2187
+ // Update translate after removing clones for animation
2385
2188
  const skip = Math.min(swiper.params.slidesPerGroupSkip, newIndex);
2386
2189
  let snapIndex = skip + Math.floor((newIndex - skip) / swiper.params.slidesPerGroup);
2387
2190
  if (snapIndex >= swiper.snapGrid.length) snapIndex = swiper.snapGrid.length - 1;
@@ -2407,7 +2210,8 @@ function loopFixDot(_temp) {
2407
2210
  }
2408
2211
  swiper.setTranslate(updateTranslate);
2409
2212
  }
2410
- // Remove slide clone ra khỏi slidesEl sau khi slideTo hoàn thành
2213
+
2214
+ // Remove clones
2411
2215
  const cloneSlides = slidesEl.querySelectorAll('[data-swiper-clone="true"]');
2412
2216
  cloneSlides.forEach(cloneSlide => {
2413
2217
  if (cloneSlide.parentNode) {
@@ -2437,7 +2241,7 @@ function loopDestroy() {
2437
2241
  params,
2438
2242
  slidesEl
2439
2243
  } = swiper;
2440
- if (!params.loop || !slidesEl || swiper.virtual && swiper.params.virtual.enabled) return;
2244
+ if (!params.loop || !slidesEl) return;
2441
2245
  swiper.recalcSlides();
2442
2246
  const newSlidesOrder = [];
2443
2247
  swiper.slides.forEach(slideEl => {
@@ -2498,7 +2302,6 @@ var grabCursor = {
2498
2302
  unsetGrabCursor
2499
2303
  };
2500
2304
 
2501
- // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd
2502
2305
  function closestElement(selector, base) {
2503
2306
  if (base === void 0) {
2504
2307
  base = this;
@@ -2507,9 +2310,7 @@ function closestElement(selector, base) {
2507
2310
  if (!el || el === getDocument() || el === getWindow()) return null;
2508
2311
  if (el.assignedSlot) el = el.assignedSlot;
2509
2312
  const found = el.closest(selector);
2510
- if (!found && !el.getRootNode) {
2511
- return null;
2512
- }
2313
+ if (!found && !el.getRootNode) return null;
2513
2314
  return found || __closestFrom(el.getRootNode().host);
2514
2315
  }
2515
2316
  return __closestFrom(base);
@@ -2537,9 +2338,7 @@ function onTouchStart(event) {
2537
2338
  if (e.originalEvent) e = e.originalEvent;
2538
2339
  const data = swiper.touchEventsData;
2539
2340
  if (e.type === 'pointerdown') {
2540
- if (data.pointerId !== null && data.pointerId !== e.pointerId) {
2541
- return;
2542
- }
2341
+ if (data.pointerId !== null && data.pointerId !== e.pointerId) return;
2543
2342
  data.pointerId = e.pointerId;
2544
2343
  } else if (e.type === 'touchstart' && e.targetTouches.length === 1) {
2545
2344
  data.touchId = e.targetTouches[0].identifier;
@@ -2556,9 +2355,7 @@ function onTouchStart(event) {
2556
2355
  } = swiper;
2557
2356
  if (!enabled) return;
2558
2357
  if (!params.simulateTouch && e.pointerType === 'mouse') return;
2559
- if (swiper.animating && params.preventInteractionOnTransition) {
2560
- return;
2561
- }
2358
+ if (swiper.animating && params.preventInteractionOnTransition) return;
2562
2359
  if (!swiper.animating && params.cssMode && params.loop) {
2563
2360
  swiper.loopFix();
2564
2361
  }
@@ -2569,8 +2366,6 @@ function onTouchStart(event) {
2569
2366
  if ('which' in e && e.which === 3) return;
2570
2367
  if ('button' in e && e.button > 0) return;
2571
2368
  if (data.isTouched && data.isMoved) return;
2572
-
2573
- // change target el for shadow root component
2574
2369
  const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';
2575
2370
  // eslint-disable-next-line
2576
2371
  const eventPath = e.composedPath ? e.composedPath() : e.path;
@@ -2579,8 +2374,6 @@ function onTouchStart(event) {
2579
2374
  }
2580
2375
  const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;
2581
2376
  const isTargetShadow = !!(e.target && e.target.shadowRoot);
2582
-
2583
- // use closestElement for shadow root element to get the actual closest for nested shadow root element
2584
2377
  if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, targetEl) : targetEl.closest(noSwipingSelector))) {
2585
2378
  swiper.allowClick = true;
2586
2379
  return;
@@ -2592,12 +2385,7 @@ function onTouchStart(event) {
2592
2385
  touches.currentY = e.pageY;
2593
2386
  const startX = touches.currentX;
2594
2387
  const startY = touches.currentY;
2595
-
2596
- // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore
2597
-
2598
- if (!preventEdgeSwipe(swiper, e, startX)) {
2599
- return;
2600
- }
2388
+ if (!preventEdgeSwipe(swiper, e, startX)) return;
2601
2389
  Object.assign(data, {
2602
2390
  isTouched: true,
2603
2391
  isMoved: false,
@@ -2626,9 +2414,6 @@ function onTouchStart(event) {
2626
2414
  if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !targetEl.isContentEditable) {
2627
2415
  e.preventDefault();
2628
2416
  }
2629
- if (params.freeMode && params.freeMode.enabled && swiper.freeMode && swiper.animating && !params.cssMode) {
2630
- swiper.freeMode.onTouchStart();
2631
- }
2632
2417
  swiper.emit('touchStart', e);
2633
2418
  }
2634
2419
 
@@ -2647,7 +2432,7 @@ function onTouchMove(event) {
2647
2432
  let e = event;
2648
2433
  if (e.originalEvent) e = e.originalEvent;
2649
2434
  if (e.type === 'pointermove') {
2650
- if (data.touchId !== null) return; // return from pointer if we use touch
2435
+ if (data.touchId !== null) return;
2651
2436
  const id = e.pointerId;
2652
2437
  if (id !== data.pointerId) return;
2653
2438
  }
@@ -2688,7 +2473,6 @@ function onTouchMove(event) {
2688
2473
  }
2689
2474
  if (params.touchReleaseOnEdges && !params.loop) {
2690
2475
  if (swiper.isVertical()) {
2691
- // Vertical
2692
2476
  if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) {
2693
2477
  data.isTouched = false;
2694
2478
  data.isMoved = false;
@@ -2790,7 +2574,6 @@ function onTouchMove(event) {
2790
2574
  swiper.wrapperEl.dispatchEvent(evt);
2791
2575
  }
2792
2576
  data.allowMomentumBounce = false;
2793
- // Grab Cursor
2794
2577
  if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
2795
2578
  swiper.setGrabCursor(true);
2796
2579
  }
@@ -2861,8 +2644,6 @@ function onTouchMove(event) {
2861
2644
  if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {
2862
2645
  data.currentTranslate = data.startTranslate;
2863
2646
  }
2864
-
2865
- // Threshold
2866
2647
  if (params.threshold > 0) {
2867
2648
  if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
2868
2649
  if (!data.allowThresholdMove) {
@@ -2880,17 +2661,12 @@ function onTouchMove(event) {
2880
2661
  }
2881
2662
  if (!params.followFinger || params.cssMode) return;
2882
2663
 
2883
- // Update active index in free mode
2884
- if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {
2664
+ // core-lite: no optional feature updates; only watchSlidesProgress
2665
+ if (params.watchSlidesProgress) {
2885
2666
  swiper.updateActiveIndex();
2886
2667
  swiper.updateSlidesClasses();
2887
2668
  }
2888
- if (params.freeMode && params.freeMode.enabled && swiper.freeMode) {
2889
- swiper.freeMode.onTouchMove();
2890
- }
2891
- // Update progress
2892
2669
  swiper.updateProgress(data.currentTranslate);
2893
- // Update translate
2894
2670
  swiper.setTranslate(data.currentTranslate);
2895
2671
  }
2896
2672
 
@@ -2902,7 +2678,7 @@ function onTouchEnd(event) {
2902
2678
  let targetTouch;
2903
2679
  const isTouchEvent = e.type === 'touchend' || e.type === 'touchcancel';
2904
2680
  if (!isTouchEvent) {
2905
- if (data.touchId !== null) return; // return from pointer if we use touch
2681
+ if (data.touchId !== null) return;
2906
2682
  if (e.pointerId !== data.pointerId) return;
2907
2683
  targetTouch = e;
2908
2684
  } else {
@@ -2911,9 +2687,7 @@ function onTouchEnd(event) {
2911
2687
  }
2912
2688
  if (['pointercancel', 'pointerout', 'pointerleave', 'contextmenu'].includes(e.type)) {
2913
2689
  const proceed = ['pointercancel', 'contextmenu'].includes(e.type) && (swiper.browser.isSafari || swiper.browser.isWebView);
2914
- if (!proceed) {
2915
- return;
2916
- }
2690
+ if (!proceed) return;
2917
2691
  }
2918
2692
  data.pointerId = null;
2919
2693
  data.touchId = null;
@@ -2931,9 +2705,7 @@ function onTouchEnd(event) {
2931
2705
  }
2932
2706
  data.allowTouchCallbacks = false;
2933
2707
  if (!data.isTouched) {
2934
- if (data.isMoved && params.grabCursor) {
2935
- swiper.setGrabCursor(false);
2936
- }
2708
+ if (data.isMoved && params.grabCursor) swiper.setGrabCursor(false);
2937
2709
  data.isMoved = false;
2938
2710
  data.startMoving = false;
2939
2711
  return;
@@ -2943,8 +2715,6 @@ function onTouchEnd(event) {
2943
2715
  if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
2944
2716
  swiper.setGrabCursor(false);
2945
2717
  }
2946
-
2947
- // Time diff
2948
2718
  const touchEndTime = now();
2949
2719
  const timeDiff = touchEndTime - data.touchStartTime;
2950
2720
 
@@ -2971,20 +2741,8 @@ function onTouchEnd(event) {
2971
2741
  data.isMoved = false;
2972
2742
  data.startMoving = false;
2973
2743
  let currentPos;
2974
- if (params.followFinger) {
2975
- currentPos = rtl ? swiper.translate : -swiper.translate;
2976
- } else {
2977
- currentPos = -data.currentTranslate;
2978
- }
2979
- if (params.cssMode) {
2980
- return;
2981
- }
2982
- if (params.freeMode && params.freeMode.enabled) {
2983
- swiper.freeMode.onTouchEnd({
2984
- currentPos
2985
- });
2986
- return;
2987
- }
2744
+ if (params.followFinger) currentPos = rtl ? swiper.translate : -swiper.translate;else currentPos = -data.currentTranslate;
2745
+ if (params.cssMode) return;
2988
2746
 
2989
2747
  // Find current slide
2990
2748
  const swipeToLast = currentPos >= -swiper.maxTranslate() && !swiper.params.loop;
@@ -3006,22 +2764,22 @@ function onTouchEnd(event) {
3006
2764
  let rewindLastIndex = null;
3007
2765
  if (params.rewind) {
3008
2766
  if (swiper.isBeginning) {
3009
- rewindLastIndex = params.virtual && params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;
2767
+ rewindLastIndex = swiper.slides.length - 1;
3010
2768
  } else if (swiper.isEnd) {
3011
2769
  rewindFirstIndex = 0;
3012
2770
  }
3013
2771
  }
3014
- // Find current slide size
3015
2772
  const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
3016
2773
  const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
3017
2774
  if (timeDiff > params.longSwipesMs) {
3018
- // Long touches
3019
2775
  if (!params.longSwipes) {
3020
2776
  swiper.slideTo(swiper.activeIndex);
3021
2777
  return;
3022
2778
  }
3023
2779
  if (swiper.swipeDirection === 'next') {
3024
- if (ratio >= params.longSwipesRatio) swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);else swiper.slideTo(stopIndex);
2780
+ if (ratio >= params.longSwipesRatio) {
2781
+ swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);
2782
+ } else swiper.slideTo(stopIndex);
3025
2783
  }
3026
2784
  if (swiper.swipeDirection === 'prev') {
3027
2785
  if (ratio > 1 - params.longSwipesRatio) {
@@ -3073,7 +2831,6 @@ function onResize() {
3073
2831
  allowSlidePrev,
3074
2832
  snapGrid
3075
2833
  } = swiper;
3076
- const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
3077
2834
 
3078
2835
  // Disable locks on resize
3079
2836
  swiper.allowSlideNext = true;
@@ -3081,15 +2838,12 @@ function onResize() {
3081
2838
  swiper.updateSize();
3082
2839
  swiper.updateSlides();
3083
2840
  swiper.updateSlidesClasses();
3084
- const isVirtualLoop = isVirtual && params.loop;
3085
- if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides && !isVirtualLoop) {
2841
+ if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides) {
3086
2842
  swiper.slideTo(swiper.slides.length - 1, 0, false, true);
2843
+ } else if (swiper.params.loop) {
2844
+ swiper.slideToLoop(swiper.realIndex, 0, false, true);
3087
2845
  } else {
3088
- if (swiper.params.loop && !isVirtual) {
3089
- swiper.slideToLoop(swiper.realIndex, 0, false, true);
3090
- } else {
3091
- swiper.slideTo(swiper.activeIndex, 0, false, true);
3092
- }
2846
+ swiper.slideTo(swiper.activeIndex, 0, false, true);
3093
2847
  }
3094
2848
  if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
3095
2849
  clearTimeout(swiper.autoplay.resizeTimeout);
@@ -3099,10 +2853,11 @@ function onResize() {
3099
2853
  }
3100
2854
  }, 500);
3101
2855
  }
2856
+
3102
2857
  // Return locks after resize
3103
2858
  swiper.allowSlidePrev = allowSlidePrev;
3104
2859
  swiper.allowSlideNext = allowSlideNext;
3105
- if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
2860
+ if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
3106
2861
  swiper.checkOverflow();
3107
2862
  }
3108
2863
  }
@@ -3156,6 +2911,10 @@ function onLoad(e) {
3156
2911
  if (swiper.params.cssMode || swiper.params.slidesPerView !== 'auto' && !swiper.params.autoHeight) {
3157
2912
  return;
3158
2913
  }
2914
+ const el = e?.target;
2915
+ // IMG, IFRAME, EMBED with width/height attributes don't change slide size — no need to call swiper.update()
2916
+ if (!el || !['IMG', 'IFRAME', 'EMBED'].includes(el.tagName)) return;
2917
+ if (el.hasAttribute('width') && el.hasAttribute('height')) return;
3159
2918
  swiper.update();
3160
2919
  }
3161
2920
 
@@ -3267,8 +3026,15 @@ var events$1 = {
3267
3026
  detachEvents
3268
3027
  };
3269
3028
 
3270
- const isGridEnabled = (swiper, params) => {
3271
- return swiper.grid && params.grid && params.grid.rows > 1;
3029
+ const toggleModule = (swiper, params, breakpointParams, prop) => {
3030
+ const wasModuleEnabled = params[prop] && params[prop].enabled;
3031
+ const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled;
3032
+ if (wasModuleEnabled && !isModuleEnabled) {
3033
+ swiper[prop].disable();
3034
+ }
3035
+ if (!wasModuleEnabled && isModuleEnabled) {
3036
+ swiper[prop].enable();
3037
+ }
3272
3038
  };
3273
3039
  function setBreakpoint() {
3274
3040
  const swiper = this;
@@ -3289,38 +3055,20 @@ function setBreakpoint() {
3289
3055
  if (!breakpoint || swiper.currentBreakpoint === breakpoint) return;
3290
3056
  const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
3291
3057
  const breakpointParams = breakpointOnlyParams || swiper.originalParams;
3292
- const wasMultiRow = isGridEnabled(swiper, params);
3293
- const isMultiRow = isGridEnabled(swiper, breakpointParams);
3294
3058
  const wasGrabCursor = swiper.params.grabCursor;
3295
3059
  const isGrabCursor = breakpointParams.grabCursor;
3296
3060
  const wasEnabled = params.enabled;
3297
- if (wasMultiRow && !isMultiRow) {
3298
- el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
3299
- swiper.emitContainerClasses();
3300
- } else if (!wasMultiRow && isMultiRow) {
3301
- el.classList.add(`${params.containerModifierClass}grid`);
3302
- if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') {
3303
- el.classList.add(`${params.containerModifierClass}grid-column`);
3304
- }
3305
- swiper.emitContainerClasses();
3306
- }
3307
3061
  if (wasGrabCursor && !isGrabCursor) {
3308
3062
  swiper.unsetGrabCursor();
3309
3063
  } else if (!wasGrabCursor && isGrabCursor) {
3310
3064
  swiper.setGrabCursor();
3311
3065
  }
3312
3066
 
3313
- // Toggle navigation, pagination, scrollbar
3314
- ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
3067
+ // Core-lite: toggle navigation & pagination only.
3068
+ const modules = ['navigation', 'pagination'];
3069
+ modules.forEach(prop => {
3315
3070
  if (typeof breakpointParams[prop] === 'undefined') return;
3316
- const wasModuleEnabled = params[prop] && params[prop].enabled;
3317
- const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled;
3318
- if (wasModuleEnabled && !isModuleEnabled) {
3319
- swiper[prop].disable();
3320
- }
3321
- if (!wasModuleEnabled && isModuleEnabled) {
3322
- swiper[prop].enable();
3323
- }
3071
+ toggleModule(swiper, params, breakpointParams, prop);
3324
3072
  });
3325
3073
  const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
3326
3074
  const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
@@ -3402,7 +3150,7 @@ var breakpoints = {
3402
3150
  getBreakpoint
3403
3151
  };
3404
3152
 
3405
- function prepareClasses(entries, prefix) {
3153
+ const prepareClasses = (entries, prefix) => {
3406
3154
  const resultClasses = [];
3407
3155
  entries.forEach(item => {
3408
3156
  if (typeof item === 'object') {
@@ -3416,7 +3164,7 @@ function prepareClasses(entries, prefix) {
3416
3164
  }
3417
3165
  });
3418
3166
  return resultClasses;
3419
- }
3167
+ };
3420
3168
  function addClasses() {
3421
3169
  const swiper = this;
3422
3170
  const {
@@ -3426,17 +3174,12 @@ function addClasses() {
3426
3174
  el,
3427
3175
  device
3428
3176
  } = swiper;
3177
+ // core-lite: removed module-specific classes
3429
3178
  // prettier-ignore
3430
3179
  const suffixes = prepareClasses(['initialized', params.direction, {
3431
- 'free-mode': swiper.params.freeMode && params.freeMode.enabled
3432
- }, {
3433
3180
  'autoheight': params.autoHeight
3434
3181
  }, {
3435
3182
  'rtl': rtl
3436
- }, {
3437
- 'grid': params.grid && params.grid.rows > 1
3438
- }, {
3439
- 'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'
3440
3183
  }, {
3441
3184
  'android': device.android
3442
3185
  }, {
@@ -3533,16 +3276,12 @@ var defaults = {
3533
3276
  autoHeight: false,
3534
3277
  // Set wrapper width
3535
3278
  setWrapperSize: false,
3536
- // Virtual Translate
3537
- virtualTranslate: false,
3538
- // Effects
3279
+ // Effects (core-lite only supports `slide`)
3539
3280
  effect: 'slide',
3540
- // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
3541
-
3542
3281
  // Breakpoints
3543
3282
  breakpoints: undefined,
3544
3283
  breakpointsBase: 'window',
3545
- // Slides grid
3284
+ // Slides
3546
3285
  spaceBetween: 0,
3547
3286
  slidesPerView: 1,
3548
3287
  slidesPerGroup: 1,
@@ -3645,7 +3384,9 @@ function moduleExtendParams(params, allModulesParams) {
3645
3384
  if (moduleParamName === 'navigation' && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].prevEl && !params[moduleParamName].nextEl) {
3646
3385
  params[moduleParamName].auto = true;
3647
3386
  }
3648
- if (['pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].el) {
3387
+
3388
+ // Core-lite: keep only pagination auto-init.
3389
+ if (moduleParamName === 'pagination' && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].el) {
3649
3390
  params[moduleParamName].auto = true;
3650
3391
  }
3651
3392
  if (!(moduleParamName in params && 'enabled' in moduleParams)) {
@@ -3771,7 +3512,6 @@ class Swiper {
3771
3512
  // Indexes
3772
3513
  activeIndex: 0,
3773
3514
  realIndex: 0,
3774
- //
3775
3515
  isBeginning: true,
3776
3516
  isEnd: false,
3777
3517
  // Props
@@ -3798,12 +3538,9 @@ class Swiper {
3798
3538
  currentTranslate: undefined,
3799
3539
  startTranslate: undefined,
3800
3540
  allowThresholdMove: undefined,
3801
- // Form elements to match
3802
3541
  focusableElements: swiper.params.focusableElements,
3803
- // Last click time
3804
3542
  lastClickTime: 0,
3805
3543
  clickTimeout: undefined,
3806
- // Velocities
3807
3544
  velocities: [],
3808
3545
  allowMomentumBounce: undefined,
3809
3546
  startMoving: undefined,
@@ -3823,7 +3560,8 @@ class Swiper {
3823
3560
  },
3824
3561
  // Images
3825
3562
  imagesToLoad: [],
3826
- imagesLoaded: 0
3563
+ imagesLoaded: 0,
3564
+ rtl: params?.rtl
3827
3565
  });
3828
3566
  swiper.emit('_swiper');
3829
3567
 
@@ -3832,7 +3570,6 @@ class Swiper {
3832
3570
  swiper.init();
3833
3571
  }
3834
3572
 
3835
- // Return app instance
3836
3573
  // eslint-disable-next-line no-constructor-return
3837
3574
  return swiper;
3838
3575
  }
@@ -3864,16 +3601,6 @@ class Swiper {
3864
3601
  getSlideIndexByData(index) {
3865
3602
  return this.getSlideIndex(this.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === index));
3866
3603
  }
3867
- getSlideIndexWhenGrid(index) {
3868
- if (this.grid && this.params.grid && this.params.grid.rows > 1) {
3869
- if (this.params.grid.fill === 'column') {
3870
- index = Math.floor(index / this.params.grid.rows);
3871
- } else if (this.params.grid.fill === 'row') {
3872
- index = index % Math.ceil(this.slides.length / this.params.grid.rows);
3873
- }
3874
- }
3875
- return index;
3876
- }
3877
3604
  recalcSlides() {
3878
3605
  const swiper = this;
3879
3606
  const {
@@ -3975,21 +3702,15 @@ class Swiper {
3975
3702
  }
3976
3703
  }
3977
3704
  } else {
3978
- // eslint-disable-next-line
3979
3705
  if (view === 'current') {
3980
3706
  for (let i = activeIndex + 1; i < slides.length; i += 1) {
3981
3707
  const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;
3982
- if (slideInView) {
3983
- spv += 1;
3984
- }
3708
+ if (slideInView) spv += 1;
3985
3709
  }
3986
3710
  } else {
3987
- // previous
3988
3711
  for (let i = activeIndex - 1; i >= 0; i -= 1) {
3989
3712
  const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;
3990
- if (slideInView) {
3991
- spv += 1;
3992
- }
3713
+ if (slideInView) spv += 1;
3993
3714
  }
3994
3715
  }
3995
3716
  }
@@ -4002,14 +3723,11 @@ class Swiper {
4002
3723
  snapGrid,
4003
3724
  params
4004
3725
  } = swiper;
4005
- // Breakpoints
4006
3726
  if (params.breakpoints) {
4007
3727
  swiper.setBreakpoint();
4008
3728
  }
4009
3729
  [...swiper.el.querySelectorAll('[loading="lazy"]')].forEach(imageEl => {
4010
- if (imageEl.complete) {
4011
- processLazyPreloader(swiper, imageEl);
4012
- }
3730
+ if (imageEl.complete) processLazyPreloader(swiper, imageEl);
4013
3731
  });
4014
3732
  swiper.updateSize();
4015
3733
  swiper.updateSlides();
@@ -4023,22 +3741,12 @@ class Swiper {
4023
3741
  swiper.updateSlidesClasses();
4024
3742
  }
4025
3743
  let translated;
4026
- if (params.freeMode && params.freeMode.enabled && !params.cssMode) {
4027
- setTranslate();
4028
- if (params.autoHeight) {
4029
- swiper.updateAutoHeight();
4030
- }
3744
+ if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !params.centeredSlides) {
3745
+ translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
4031
3746
  } else {
4032
- if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !params.centeredSlides) {
4033
- const slides = swiper.virtual && params.virtual.enabled ? swiper.virtual.slides : swiper.slides;
4034
- translated = swiper.slideTo(slides.length - 1, 0, false, true);
4035
- } else {
4036
- translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
4037
- }
4038
- if (!translated) {
4039
- setTranslate();
4040
- }
3747
+ translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
4041
3748
  }
3749
+ if (!translated) setTranslate();
4042
3750
  if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
4043
3751
  swiper.checkOverflow();
4044
3752
  }
@@ -4051,7 +3759,6 @@ class Swiper {
4051
3759
  const swiper = this;
4052
3760
  const currentDirection = swiper.params.direction;
4053
3761
  if (!newDirection) {
4054
- // eslint-disable-next-line
4055
3762
  newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
4056
3763
  }
4057
3764
  if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {
@@ -4089,15 +3796,11 @@ class Swiper {
4089
3796
  mount(element) {
4090
3797
  const swiper = this;
4091
3798
  if (swiper.mounted) return true;
4092
-
4093
- // Find el
4094
3799
  let el = element || swiper.params.el;
4095
3800
  if (typeof el === 'string') {
4096
3801
  el = document.querySelector(el);
4097
3802
  }
4098
- if (!el) {
4099
- return false;
4100
- }
3803
+ if (!el) return false;
4101
3804
  el.swiper = swiper;
4102
3805
  if (el.parentNode && el.parentNode.host && el.parentNode.host.nodeName === swiper.params.swiperElementNodeName.toUpperCase()) {
4103
3806
  swiper.isElement = true;
@@ -4108,12 +3811,10 @@ class Swiper {
4108
3811
  const getWrapper = () => {
4109
3812
  if (el && el.shadowRoot && el.shadowRoot.querySelector) {
4110
3813
  const res = el.shadowRoot.querySelector(getWrapperSelector());
4111
- // Children needs to return slot items
4112
3814
  return res;
4113
3815
  }
4114
3816
  return elementChildren(el, getWrapperSelector())[0];
4115
3817
  };
4116
- // Find Wrapper
4117
3818
  let wrapperEl = getWrapper();
4118
3819
  if (!wrapperEl && swiper.params.createElements) {
4119
3820
  wrapperEl = createElement('div', swiper.params.wrapperClass);
@@ -4122,6 +3823,8 @@ class Swiper {
4122
3823
  wrapperEl.append(slideEl);
4123
3824
  });
4124
3825
  }
3826
+ const rtl = swiper.params.rtl ?? (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl');
3827
+ const wrongRTL = false;
4125
3828
  Object.assign(swiper, {
4126
3829
  el,
4127
3830
  wrapperEl,
@@ -4129,9 +3832,9 @@ class Swiper {
4129
3832
  hostEl: swiper.isElement ? el.parentNode.host : el,
4130
3833
  mounted: true,
4131
3834
  // RTL
4132
- rtl: el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl',
4133
- rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl'),
4134
- wrongRTL: elementStyle(wrapperEl, 'display') === '-webkit-box'
3835
+ rtl,
3836
+ rtlTranslate: swiper.params.direction === 'horizontal' && rtl,
3837
+ wrongRTL
4135
3838
  });
4136
3839
  return true;
4137
3840
  }
@@ -4148,7 +3851,6 @@ class Swiper {
4148
3851
  const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
4149
3852
  const swiperTranslate = structuredClone(swiper.snapGrid[1]);
4150
3853
  if (isFirstSlide) {
4151
- // Move last item to first position when at first slide
4152
3854
  const lastSlide = slides.at(-1);
4153
3855
  lastSlide.swiperLoopMoveDOM = true;
4154
3856
  swiper.slidesEl.prepend(lastSlide);
@@ -4160,7 +3862,6 @@ class Swiper {
4160
3862
  swiper.setTransition(speed);
4161
3863
  swiper.setTranslate(-swiperTranslate);
4162
3864
  } else if (isLastSlide) {
4163
- // Move first item to last position when at last slide
4164
3865
  const firstSlide = slides[0];
4165
3866
  firstSlide.swiperLoopMoveDOM = true;
4166
3867
  swiper.slidesEl.append(firstSlide);
@@ -4181,42 +3882,24 @@ class Swiper {
4181
3882
  const mounted = swiper.mount(el);
4182
3883
  if (mounted === false) return swiper;
4183
3884
  swiper.emit('beforeInit');
4184
-
4185
- // Set breakpoint
4186
3885
  if (swiper.params.breakpoints) {
4187
3886
  swiper.setBreakpoint();
4188
3887
  }
4189
-
4190
- // Add Classes
4191
3888
  swiper.addClasses();
4192
-
4193
- // Update size
4194
3889
  swiper.updateSize();
4195
-
4196
- // Update slides
4197
3890
  swiper.updateSlides();
4198
3891
  if (swiper.params.watchOverflow) {
4199
3892
  swiper.checkOverflow();
4200
3893
  }
4201
-
4202
- // Set Grab Cursor
4203
3894
  if (swiper.params.grabCursor && swiper.enabled) {
4204
3895
  swiper.setGrabCursor();
4205
3896
  }
4206
3897
 
4207
- // Slide To Initial Slide
4208
- if (swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) {
4209
- swiper.slideTo(swiper.params.initialSlide + swiper.virtual.slidesBefore, 0, swiper.params.runCallbacksOnInit, false, true);
4210
- } else {
4211
- swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
4212
- }
4213
-
4214
- // Create loop
3898
+ // Slide to initial slide (core-lite: no optional feature initial offsets)
3899
+ swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
4215
3900
  if (swiper.params.loop) {
4216
3901
  swiper.loopCreate(undefined, true);
4217
3902
  }
4218
-
4219
- // Attach events
4220
3903
  swiper.attachEvents();
4221
3904
  const lazyElements = [...swiper.el.querySelectorAll('[loading="lazy"]')];
4222
3905
  if (swiper.isElement) {
@@ -4226,16 +3909,11 @@ class Swiper {
4226
3909
  if (imageEl.complete) {
4227
3910
  processLazyPreloader(swiper, imageEl);
4228
3911
  } else {
4229
- imageEl.addEventListener('load', e => {
4230
- processLazyPreloader(swiper, e.target);
4231
- });
3912
+ imageEl.addEventListener('load', e => processLazyPreloader(swiper, e.target));
4232
3913
  }
4233
3914
  });
4234
3915
  preload(swiper);
4235
-
4236
- // Init Flag
4237
3916
  swiper.initialized = true;
4238
- preload(swiper);
4239
3917
 
4240
3918
  // Emit
4241
3919
  swiper.emit('init');
@@ -4260,27 +3938,15 @@ class Swiper {
4260
3938
  return null;
4261
3939
  }
4262
3940
  swiper.emit('beforeDestroy');
4263
-
4264
- // Init Flag
4265
3941
  swiper.initialized = false;
4266
-
4267
- // Detach events
4268
3942
  swiper.detachEvents();
4269
-
4270
- // Destroy loop
4271
3943
  if (params.loop) {
4272
3944
  swiper.loopDestroy();
4273
3945
  }
4274
-
4275
- // Cleanup styles
4276
3946
  if (cleanStyles) {
4277
3947
  swiper.removeClasses();
4278
- if (el && typeof el !== 'string') {
4279
- el.removeAttribute('style');
4280
- }
4281
- if (wrapperEl) {
4282
- wrapperEl.removeAttribute('style');
4283
- }
3948
+ if (el && typeof el !== 'string') el.removeAttribute('style');
3949
+ if (wrapperEl) wrapperEl.removeAttribute('style');
4284
3950
  if (slides && slides.length) {
4285
3951
  slides.forEach(slideEl => {
4286
3952
  slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
@@ -4290,8 +3956,6 @@ class Swiper {
4290
3956
  }
4291
3957
  }
4292
3958
  swiper.emit('destroy');
4293
-
4294
- // Detach emitter events
4295
3959
  Object.keys(swiper.eventsListeners).forEach(eventName => {
4296
3960
  swiper.off(eventName);
4297
3961
  });