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