@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.
package/swiper-element.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Swiper Custom Element 0.0.15
2
+ * Swiper Custom Element 0.0.17-dev.1
3
3
  * Gem SDK - Swiper, Customized of swiper
4
4
  * https://swiperjs.com
5
5
  *
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Released under the MIT License
9
9
  *
10
- * Released on: March 20, 2026
10
+ * Released on: March 23, 2026
11
11
  */
12
12
 
13
13
  (function () {
@@ -189,7 +189,7 @@
189
189
  function now() {
190
190
  return Date.now();
191
191
  }
192
- function getComputedStyle$1(el) {
192
+ function getComputedStyle(el) {
193
193
  const window = getWindow();
194
194
  let style;
195
195
  if (window.getComputedStyle) {
@@ -211,7 +211,7 @@
211
211
  let matrix;
212
212
  let curTransform;
213
213
  let transformMatrix;
214
- const curStyle = getComputedStyle$1(el);
214
+ const curStyle = getComputedStyle(el);
215
215
  if (window.WebKitCSSMatrix) {
216
216
  curTransform = curStyle.transform || curStyle.webkitTransform;
217
217
  if (curTransform.split(',').length > 6) {
@@ -459,6 +459,55 @@
459
459
  el.innerHTML = html;
460
460
  }
461
461
  }
462
+ function getComputedStyleValue(params) {
463
+ const {
464
+ styles,
465
+ swiper,
466
+ property
467
+ } = params ?? {};
468
+ return parseFloat(styles.getPropertyValue(swiper.getDirectionLabel(property))) || 0;
469
+ }
470
+ function computeAutoSlideSize(params) {
471
+ const {
472
+ el,
473
+ swiper
474
+ } = params ?? {};
475
+ const styles = getComputedStyle(el);
476
+ const width = getComputedStyleValue({
477
+ styles,
478
+ swiper,
479
+ property: 'width'
480
+ });
481
+ const paddingLeft = getComputedStyleValue({
482
+ styles,
483
+ swiper,
484
+ property: 'padding-left'
485
+ });
486
+ const paddingRight = getComputedStyleValue({
487
+ styles,
488
+ swiper,
489
+ property: 'padding-right'
490
+ });
491
+ const marginLeft = getComputedStyleValue({
492
+ styles,
493
+ swiper,
494
+ property: 'margin-left'
495
+ });
496
+ const marginRight = getComputedStyleValue({
497
+ styles,
498
+ swiper,
499
+ property: 'margin-right'
500
+ });
501
+ const boxSizing = styles.getPropertyValue('box-sizing');
502
+ if (boxSizing && boxSizing === 'border-box') {
503
+ return width + marginLeft + marginRight;
504
+ }
505
+ const {
506
+ clientWidth,
507
+ offsetWidth
508
+ } = slideEl;
509
+ return width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);
510
+ }
462
511
 
463
512
  let support;
464
513
  function calcSupport() {
@@ -841,9 +890,6 @@
841
890
 
842
891
  function updateSlides() {
843
892
  const swiper = this;
844
- function getDirectionPropertyValue(node, label) {
845
- return parseFloat(node.getPropertyValue(swiper.getDirectionLabel(label)) || 0);
846
- }
847
893
  const params = swiper.params;
848
894
  const {
849
895
  wrapperEl,
@@ -852,10 +898,8 @@
852
898
  rtlTranslate: rtl,
853
899
  wrongRTL
854
900
  } = swiper;
855
- const isVirtual = swiper.virtual && params.virtual.enabled;
856
- const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
857
901
  const slides = elementChildren(slidesEl, `.${swiper.params.slideClass}, swiper-slide`);
858
- const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
902
+ const slidesLength = slides.length;
859
903
  let snapGrid = [];
860
904
  const slidesGrid = [];
861
905
  const slidesSizesGrid = [];
@@ -873,15 +917,15 @@
873
917
  let slidePosition = -offsetBefore;
874
918
  let prevSlideSize = 0;
875
919
  let index = 0;
876
- if (typeof swiperSize === 'undefined') {
877
- return;
878
- }
920
+ if (typeof swiperSize === 'undefined') return;
879
921
  if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
880
922
  spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;
881
923
  } else if (typeof spaceBetween === 'string') {
882
924
  spaceBetween = parseFloat(spaceBetween);
883
925
  }
884
- swiper.virtualSize = -spaceBetween;
926
+
927
+ // core-lite: compute total slides size without optional modules
928
+ swiper.slidesTotalSize = -spaceBetween;
885
929
 
886
930
  // reset margins
887
931
  slides.forEach(slideEl => {
@@ -899,67 +943,90 @@
899
943
  setCSSProperty(wrapperEl, '--swiper-centered-offset-before', '');
900
944
  setCSSProperty(wrapperEl, '--swiper-centered-offset-after', '');
901
945
  }
902
- const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;
903
- if (gridEnabled) {
904
- swiper.grid.initSlides(slides);
905
- } else if (swiper.grid) {
906
- swiper.grid.unsetSlides();
907
- }
908
946
 
909
947
  // Calc slides
910
948
  let slideSize;
911
- const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {
912
- return typeof params.breakpoints[key].slidesPerView !== 'undefined';
913
- }).length > 0;
914
- for (let i = 0; i < slidesLength; i += 1) {
915
- slideSize = 0;
916
- let slide;
917
- if (slides[i]) slide = slides[i];
918
- if (gridEnabled) {
919
- swiper.grid.updateSlide(i, slide, slides);
920
- }
921
- if (slides[i] && elementStyle(slide, 'display') === 'none') continue; // eslint-disable-line
949
+ const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => typeof params.breakpoints[key].slidesPerView !== 'undefined').length > 0;
950
+ const isAutoSlidesPerView = params.slidesPerView === 'auto';
922
951
 
923
- if (params.slidesPerView === 'auto') {
952
+ // --- Phase 1: Batch DOM writes (grid updates, width/transform resets) ---
953
+ // Moving all style writes before any reads prevents per-slide forced reflows
954
+
955
+ const savedTransforms = [];
956
+ if (isAutoSlidesPerView) {
957
+ for (let i = 0; i < slidesLength; i += 1) {
958
+ if (!slides[i]) continue;
924
959
  if (shouldResetSlideSize) {
925
960
  slides[i].style[swiper.getDirectionLabel('width')] = ``;
926
961
  }
927
- const slideStyles = getComputedStyle(slide);
928
- const currentTransform = slide.style.transform;
929
- const currentWebKitTransform = slide.style.webkitTransform;
962
+ const currentTransform = slides[i].style.transform;
963
+ const currentWebKitTransform = slides[i].style.webkitTransform;
964
+ savedTransforms[i] = {
965
+ transform: currentTransform,
966
+ webkitTransform: currentWebKitTransform
967
+ };
930
968
  if (currentTransform) {
931
- slide.style.transform = 'none';
969
+ slides[i].style.transform = 'none';
932
970
  }
933
971
  if (currentWebKitTransform) {
934
- slide.style.webkitTransform = 'none';
972
+ slides[i].style.webkitTransform = 'none';
935
973
  }
974
+ }
975
+ }
976
+
977
+ // --- Phase 2: Batch DOM reads (single forced reflow for all slides) ---
978
+ // Read wrapper offset here (before Phase 3 writes) so it's batched with slide reads, not after
979
+ const wrapperOffset = swiper.isElement ? swiper.wrapperEl[`offset${swiper.isHorizontal() ? 'Left' : 'Top'}`] : 0;
980
+ const slideVisible = [];
981
+ const slideSizes = [];
982
+ for (let i = 0; i < slidesLength; i += 1) {
983
+ if (!slides[i]) {
984
+ slideVisible[i] = false;
985
+ continue;
986
+ }
987
+ if (elementStyle(slides[i], 'display') === 'none') {
988
+ slideVisible[i] = false;
989
+ continue;
990
+ }
991
+ slideVisible[i] = true;
992
+
993
+ // Cache offsetHeight for autoHeight (batched here to avoid a separate forced reflow in updateAutoHeight)
994
+ if (params.autoHeight) {
995
+ slides[i].swiperSlideHeight = slides[i]['offsetHeight'];
996
+ }
997
+ if (isAutoSlidesPerView) {
936
998
  if (params.roundLengths) {
937
- slideSize = swiper.isHorizontal() ? elementOuterSize(slide, 'width', true) : elementOuterSize(slide, 'height', true);
999
+ slideSizes[i] = swiper.isHorizontal() ? elementOuterSize(slides[i], 'width', true) : elementOuterSize(slides[i], 'height', true);
938
1000
  } else {
939
- // eslint-disable-next-line
940
- const width = getDirectionPropertyValue(slideStyles, 'width');
941
- const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');
942
- const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');
943
- const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');
944
- const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');
945
- const boxSizing = slideStyles.getPropertyValue('box-sizing');
946
- if (boxSizing && boxSizing === 'border-box') {
947
- slideSize = width + marginLeft + marginRight;
948
- } else {
949
- const {
950
- clientWidth,
951
- offsetWidth
952
- } = slide;
953
- slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);
954
- }
1001
+ slideSizes[i] = computeAutoSlideSize({
1002
+ el: slides[i],
1003
+ swiper
1004
+ });
955
1005
  }
956
- if (currentTransform) {
957
- slide.style.transform = currentTransform;
1006
+ if (params.roundLengths) slideSizes[i] = Math.floor(slideSizes[i]);
1007
+ }
1008
+ }
1009
+
1010
+ // --- Phase 3: Restore transforms (batch write) ---
1011
+ if (isAutoSlidesPerView) {
1012
+ for (let i = 0; i < slidesLength; i += 1) {
1013
+ if (!savedTransforms[i]) continue;
1014
+ if (savedTransforms[i].transform) {
1015
+ slides[i].style.transform = savedTransforms[i].transform;
958
1016
  }
959
- if (currentWebKitTransform) {
960
- slide.style.webkitTransform = currentWebKitTransform;
1017
+ if (savedTransforms[i].webkitTransform) {
1018
+ slides[i].style.webkitTransform = savedTransforms[i].webkitTransform;
961
1019
  }
962
- if (params.roundLengths) slideSize = Math.floor(slideSize);
1020
+ }
1021
+ }
1022
+
1023
+ // --- Phase 4: Calculate positions + set sizes (math + deferred writes) ---
1024
+ const cssOverflowAdj = swiper.cssOverflowAdjustment();
1025
+ for (let i = 0; i < slidesLength; i += 1) {
1026
+ slideSize = 0;
1027
+ if (!slideVisible[i]) continue;
1028
+ if (isAutoSlidesPerView) {
1029
+ slideSize = slideSizes[i] || 0;
963
1030
  } else {
964
1031
  slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;
965
1032
  if (params.roundLengths) slideSize = Math.floor(slideSize);
@@ -967,13 +1034,13 @@
967
1034
  slides[i].style[swiper.getDirectionLabel('width')] = `${slideSize}px`;
968
1035
  }
969
1036
  }
970
- if (slides[i]) {
971
- slides[i].swiperSlideSize = slideSize;
972
- }
1037
+ if (slides[i]) slides[i].swiperSlideSize = slideSize;
973
1038
  slidesSizesGrid.push(slideSize);
974
1039
  if (params.centeredSlides) {
975
1040
  slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
976
- if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
1041
+ if (prevSlideSize === 0 && i !== 0) {
1042
+ slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
1043
+ }
977
1044
  if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
978
1045
  if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
979
1046
  if (params.roundLengths) slidePosition = Math.floor(slidePosition);
@@ -981,55 +1048,42 @@
981
1048
  slidesGrid.push(slidePosition);
982
1049
  } else {
983
1050
  if (params.roundLengths) slidePosition = Math.floor(slidePosition);
984
- if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);
1051
+ if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) {
1052
+ snapGrid.push(slidePosition);
1053
+ }
985
1054
  slidesGrid.push(slidePosition);
986
1055
  slidePosition = slidePosition + slideSize + spaceBetween;
987
1056
  }
988
- swiper.virtualSize += slideSize + spaceBetween;
1057
+
1058
+ // Set swiperSlideOffset from computed grid position (avoids DOM reads in updateSlidesOffset)
1059
+ if (slides[i]) {
1060
+ slides[i].swiperSlideOffset = slidesGrid[slidesGrid.length - 1] - cssOverflowAdj - wrapperOffset;
1061
+ }
1062
+ swiper.slidesTotalSize += slideSize + spaceBetween;
989
1063
  prevSlideSize = slideSize;
990
1064
  index += 1;
991
1065
  }
992
- swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
993
- if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
994
- wrapperEl.style.width = `${swiper.virtualSize + spaceBetween}px`;
1066
+ swiper.slidesTotalSize = Math.max(swiper.slidesTotalSize, swiperSize) + offsetAfter;
1067
+ if (rtl && wrongRTL && params.effect === 'slide') {
1068
+ wrapperEl.style.width = `${swiper.slidesTotalSize + spaceBetween}px`;
995
1069
  }
996
1070
  if (params.setWrapperSize) {
997
- wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`;
998
- }
999
- if (gridEnabled) {
1000
- swiper.grid.updateWrapperSize(slideSize, snapGrid);
1071
+ wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.slidesTotalSize + spaceBetween}px`;
1001
1072
  }
1002
1073
 
1003
- // Remove last grid elements depending on width
1074
+ // Remove last snap points depending on width (non-centered)
1004
1075
  if (!params.centeredSlides) {
1005
1076
  const newSlidesGrid = [];
1006
1077
  for (let i = 0; i < snapGrid.length; i += 1) {
1007
1078
  let slidesGridItem = snapGrid[i];
1008
1079
  if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
1009
- if (snapGrid[i] <= swiper.virtualSize - swiperSize) {
1080
+ if (snapGrid[i] <= swiper.slidesTotalSize - swiperSize) {
1010
1081
  newSlidesGrid.push(slidesGridItem);
1011
1082
  }
1012
1083
  }
1013
1084
  snapGrid = newSlidesGrid;
1014
- if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
1015
- snapGrid.push(swiper.virtualSize - swiperSize);
1016
- }
1017
- }
1018
- if (isVirtual && params.loop) {
1019
- const size = slidesSizesGrid[0] + spaceBetween;
1020
- if (params.slidesPerGroup > 1) {
1021
- const groups = Math.ceil((swiper.virtual.slidesBefore + swiper.virtual.slidesAfter) / params.slidesPerGroup);
1022
- const groupSize = size * params.slidesPerGroup;
1023
- for (let i = 0; i < groups; i += 1) {
1024
- snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize);
1025
- }
1026
- }
1027
- for (let i = 0; i < swiper.virtual.slidesBefore + swiper.virtual.slidesAfter; i += 1) {
1028
- if (params.slidesPerGroup === 1) {
1029
- snapGrid.push(snapGrid[snapGrid.length - 1] + size);
1030
- }
1031
- slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size);
1032
- swiper.virtualSize += size;
1085
+ if (Math.floor(swiper.slidesTotalSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
1086
+ snapGrid.push(swiper.slidesTotalSize - swiperSize);
1033
1087
  }
1034
1088
  }
1035
1089
  if (snapGrid.length === 0) snapGrid = [0];
@@ -1037,9 +1091,7 @@
1037
1091
  const key = swiper.isHorizontal() && rtl ? 'marginLeft' : swiper.getDirectionLabel('marginRight');
1038
1092
  slides.filter((_, slideIndex) => {
1039
1093
  if (!params.cssMode || params.loop) return true;
1040
- if (slideIndex === slides.length - 1) {
1041
- return false;
1042
- }
1094
+ if (slideIndex === slides.length - 1) return false;
1043
1095
  return true;
1044
1096
  }).forEach(slideEl => {
1045
1097
  slideEl.style[key] = `${spaceBetween}px`;
@@ -1089,7 +1141,9 @@
1089
1141
  swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);
1090
1142
  swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);
1091
1143
  }
1092
- if (slidesLength !== previousSlidesLength) {
1144
+
1145
+ // Emit changes
1146
+ if (slidesLength !== slides.length) {
1093
1147
  swiper.emit('slidesLengthChange');
1094
1148
  }
1095
1149
  if (snapGrid.length !== previousSnapGridLength) {
@@ -1100,10 +1154,12 @@
1100
1154
  swiper.emit('slidesGridLengthChange');
1101
1155
  }
1102
1156
  if (params.watchSlidesProgress) {
1103
- swiper.updateSlidesOffset();
1157
+ swiper.updateSlidesOffset({
1158
+ isCalculatedFromUpdateSlides: true
1159
+ });
1104
1160
  }
1105
1161
  swiper.emit('slidesUpdated');
1106
- if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) {
1162
+ if (!params.cssMode && params.effect === 'slide') {
1107
1163
  const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`;
1108
1164
  const hasClassBackfaceClassAdded = swiper.el.classList.contains(backFaceHiddenClass);
1109
1165
  if (slidesLength <= params.maxBackfaceHiddenSlides) {
@@ -1117,20 +1173,13 @@
1117
1173
  function updateAutoHeight(speed) {
1118
1174
  const swiper = this;
1119
1175
  const activeSlides = [];
1120
- const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
1121
- let newHeight = 0;
1122
- let i;
1123
1176
  if (typeof speed === 'number') {
1124
1177
  swiper.setTransition(speed);
1125
1178
  } else if (speed === true) {
1126
1179
  swiper.setTransition(swiper.params.speed);
1127
1180
  }
1128
- const getSlideByIndex = index => {
1129
- if (isVirtual) {
1130
- return swiper.slides[swiper.getSlideIndexByData(index)];
1131
- }
1132
- return swiper.slides[index];
1133
- };
1181
+ const getSlideByIndex = index => swiper.slides[index];
1182
+
1134
1183
  // Find slides currently in view
1135
1184
  if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
1136
1185
  if (swiper.params.centeredSlides) {
@@ -1138,9 +1187,9 @@
1138
1187
  activeSlides.push(slide);
1139
1188
  });
1140
1189
  } else {
1141
- for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
1190
+ for (let i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
1142
1191
  const index = swiper.activeIndex + i;
1143
- if (index > swiper.slides.length && !isVirtual) break;
1192
+ if (index > swiper.slides.length) break;
1144
1193
  activeSlides.push(getSlideByIndex(index));
1145
1194
  }
1146
1195
  }
@@ -1149,18 +1198,23 @@
1149
1198
  }
1150
1199
 
1151
1200
  // Find new height from highest slide in view
1152
- for (i = 0; i < activeSlides.length; i += 1) {
1201
+ let newHeight = 0;
1202
+ for (let i = 0; i < activeSlides.length; i += 1) {
1153
1203
  if (typeof activeSlides[i] !== 'undefined') {
1154
- const height = activeSlides[i].offsetHeight;
1204
+ const height = activeSlides[i].swiperSlideHeight ?? activeSlides[i]['offsetHeight'];
1155
1205
  newHeight = height > newHeight ? height : newHeight;
1156
1206
  }
1157
1207
  }
1158
-
1159
- // Update Height
1160
1208
  if (newHeight || newHeight === 0) swiper.wrapperEl.style.height = `${newHeight}px`;
1161
1209
  }
1162
1210
 
1163
- function updateSlidesOffset() {
1211
+ function updateSlidesOffset(params) {
1212
+ const {
1213
+ isCalculatedFromUpdateSlides = false
1214
+ } = params ?? {};
1215
+ if (isCalculatedFromUpdateSlides) {
1216
+ return;
1217
+ }
1164
1218
  const swiper = this;
1165
1219
  const slides = swiper.slides;
1166
1220
  // eslint-disable-next-line
@@ -1301,46 +1355,16 @@
1301
1355
  slidesEl,
1302
1356
  activeIndex
1303
1357
  } = swiper;
1304
- const isVirtual = swiper.virtual && params.virtual.enabled;
1305
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
1306
- const getFilteredSlide = selector => {
1307
- return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
1308
- };
1309
- let activeSlide;
1310
- let prevSlide;
1358
+ const getNextSlide = slideEl => elementNextAll(slideEl, `.${params.slideClass}, swiper-slide`)[0];
1359
+ const getPrevSlide = slideEl => elementPrevAll(slideEl, `.${params.slideClass}, swiper-slide`)[0];
1360
+ const activeSlide = slides[activeIndex];
1311
1361
  let nextSlide;
1312
- if (isVirtual) {
1313
- if (params.loop) {
1314
- let slideIndex = activeIndex - swiper.virtual.slidesBefore;
1315
- if (slideIndex < 0) slideIndex = swiper.virtual.slides.length + slideIndex;
1316
- if (slideIndex >= swiper.virtual.slides.length) slideIndex -= swiper.virtual.slides.length;
1317
- activeSlide = getFilteredSlide(`[data-swiper-slide-index="${slideIndex}"]`);
1318
- } else {
1319
- activeSlide = getFilteredSlide(`[data-swiper-slide-index="${activeIndex}"]`);
1320
- }
1321
- } else {
1322
- if (gridEnabled) {
1323
- activeSlide = slides.find(slideEl => slideEl.column === activeIndex);
1324
- nextSlide = slides.find(slideEl => slideEl.column === activeIndex + 1);
1325
- prevSlide = slides.find(slideEl => slideEl.column === activeIndex - 1);
1326
- } else {
1327
- activeSlide = slides[activeIndex];
1328
- }
1329
- }
1362
+ let prevSlide;
1330
1363
  if (activeSlide) {
1331
- if (!gridEnabled) {
1332
- // Next Slide
1333
- nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
1334
- if (params.loop && !nextSlide) {
1335
- nextSlide = slides[0];
1336
- }
1337
-
1338
- // Prev Slide
1339
- prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
1340
- if (params.loop && !prevSlide === 0) {
1341
- prevSlide = slides[slides.length - 1];
1342
- }
1343
- }
1364
+ nextSlide = getNextSlide(activeSlide);
1365
+ prevSlide = getPrevSlide(activeSlide);
1366
+ if (params.loop && !nextSlide) nextSlide = slides[0];
1367
+ if (params.loop && !prevSlide) prevSlide = slides[slides.length - 1];
1344
1368
  }
1345
1369
  slides.forEach(slideEl => {
1346
1370
  toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass);
@@ -1431,7 +1455,6 @@
1431
1455
  activeIndex = i;
1432
1456
  }
1433
1457
  }
1434
- // Normalize slideIndex
1435
1458
  if (params.normalizeSlideIndex) {
1436
1459
  if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;
1437
1460
  }
@@ -1449,16 +1472,6 @@
1449
1472
  } = swiper;
1450
1473
  let activeIndex = newActiveIndex;
1451
1474
  let snapIndex;
1452
- const getVirtualRealIndex = aIndex => {
1453
- let realIndex = aIndex - swiper.virtual.slidesBefore;
1454
- if (realIndex < 0) {
1455
- realIndex = swiper.virtual.slides.length + realIndex;
1456
- }
1457
- if (realIndex >= swiper.virtual.slides.length) {
1458
- realIndex -= swiper.virtual.slides.length;
1459
- }
1460
- return realIndex;
1461
- };
1462
1475
  if (typeof activeIndex === 'undefined') {
1463
1476
  activeIndex = getActiveIndexByTranslate(swiper);
1464
1477
  }
@@ -1476,32 +1489,12 @@
1476
1489
  }
1477
1490
  return;
1478
1491
  }
1479
- if (activeIndex === previousIndex && swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) {
1480
- swiper.realIndex = getVirtualRealIndex(activeIndex);
1481
- return;
1482
- }
1483
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
1484
-
1485
- // Get real index
1486
- let realIndex;
1487
- if (swiper.virtual && params.virtual.enabled && params.loop) {
1488
- realIndex = getVirtualRealIndex(activeIndex);
1489
- } else if (gridEnabled) {
1490
- const firstSlideInColumn = swiper.slides.find(slideEl => slideEl.column === activeIndex);
1491
- let activeSlideIndex = parseInt(firstSlideInColumn.getAttribute('data-swiper-slide-index'), 10);
1492
- if (Number.isNaN(activeSlideIndex)) {
1493
- activeSlideIndex = Math.max(swiper.slides.indexOf(firstSlideInColumn), 0);
1494
- }
1495
- realIndex = Math.floor(activeSlideIndex / params.grid.rows);
1496
- } else if (swiper.slides[activeIndex]) {
1492
+ let realIndex = activeIndex;
1493
+ if (swiper.slides[activeIndex]) {
1497
1494
  const slideIndex = swiper.slides[activeIndex].getAttribute('data-swiper-slide-index');
1498
1495
  if (slideIndex) {
1499
1496
  realIndex = parseInt(slideIndex, 10);
1500
- } else {
1501
- realIndex = activeIndex;
1502
1497
  }
1503
- } else {
1504
- realIndex = activeIndex;
1505
1498
  }
1506
1499
  Object.assign(swiper, {
1507
1500
  previousSnapIndex,
@@ -1548,11 +1541,7 @@
1548
1541
  }
1549
1542
  if (slide && slideFound) {
1550
1543
  swiper.clickedSlide = slide;
1551
- if (swiper.virtual && swiper.params.virtual.enabled) {
1552
- swiper.clickedIndex = parseInt(slide.getAttribute('data-swiper-slide-index'), 10);
1553
- } else {
1554
- swiper.clickedIndex = slideIndex;
1555
- }
1544
+ swiper.clickedIndex = slideIndex;
1556
1545
  } else {
1557
1546
  swiper.clickedSlide = undefined;
1558
1547
  swiper.clickedIndex = undefined;
@@ -1586,9 +1575,6 @@
1586
1575
  translate,
1587
1576
  wrapperEl
1588
1577
  } = swiper;
1589
- if (params.virtualTranslate) {
1590
- return rtl ? -translate : translate;
1591
- }
1592
1578
  if (params.cssMode) {
1593
1579
  return translate;
1594
1580
  }
@@ -1622,7 +1608,7 @@
1622
1608
  swiper.translate = swiper.isHorizontal() ? x : y;
1623
1609
  if (params.cssMode) {
1624
1610
  wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;
1625
- } else if (!params.virtualTranslate) {
1611
+ } else {
1626
1612
  if (swiper.isHorizontal()) {
1627
1613
  x -= swiper.cssOverflowAdjustment();
1628
1614
  } else {
@@ -1859,7 +1845,6 @@
1859
1845
  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
1860
1846
  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
1861
1847
  const translate = -snapGrid[snapIndex];
1862
- // Normalize slideIndex
1863
1848
  if (params.normalizeSlideIndex) {
1864
1849
  for (let i = 0; i < slidesGrid.length; i += 1) {
1865
1850
  const normalizedTranslate = -Math.floor(translate * 100);
@@ -1876,33 +1861,24 @@
1876
1861
  }
1877
1862
  }
1878
1863
  }
1864
+
1879
1865
  // Directions locks
1880
1866
  if (swiper.initialized && slideIndex !== activeIndex) {
1881
1867
  if (!swiper.allowSlideNext && (rtl ? translate > swiper.translate && translate > swiper.minTranslate() : translate < swiper.translate && translate < swiper.minTranslate())) {
1882
1868
  return false;
1883
1869
  }
1884
1870
  if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
1885
- if ((activeIndex || 0) !== slideIndex) {
1886
- return false;
1887
- }
1871
+ if ((activeIndex || 0) !== slideIndex) return false;
1888
1872
  }
1889
1873
  }
1890
1874
  if (slideIndex !== (previousIndex || 0) && runCallbacks) {
1891
1875
  swiper.emit('beforeSlideChangeStart');
1892
1876
  }
1893
-
1894
- // Update progress
1895
1877
  swiper.updateProgress(translate);
1896
1878
  let direction;
1897
1879
  if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset';
1898
-
1899
- // initial virtual
1900
- const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
1901
- const isInitialVirtual = isVirtual && initial;
1902
- // Update Index
1903
- if (!isInitialVirtual && (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate)) {
1880
+ if (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate) {
1904
1881
  swiper.updateActiveIndex(slideIndex);
1905
- // Update Height
1906
1882
  if (params.autoHeight) {
1907
1883
  swiper.updateAutoHeight();
1908
1884
  }
@@ -1920,24 +1896,7 @@
1920
1896
  const isH = swiper.isHorizontal();
1921
1897
  const t = rtl ? translate : -translate;
1922
1898
  if (speed === 0) {
1923
- if (isVirtual) {
1924
- swiper.wrapperEl.style.scrollSnapType = 'none';
1925
- swiper._immediateVirtual = true;
1926
- }
1927
- if (isVirtual && !swiper._cssModeVirtualInitialSet && swiper.params.initialSlide > 0) {
1928
- swiper._cssModeVirtualInitialSet = true;
1929
- requestAnimationFrame(() => {
1930
- wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
1931
- });
1932
- } else {
1933
- wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
1934
- }
1935
- if (isVirtual) {
1936
- requestAnimationFrame(() => {
1937
- swiper.wrapperEl.style.scrollSnapType = '';
1938
- swiper._immediateVirtual = false;
1939
- });
1940
- }
1899
+ wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
1941
1900
  } else {
1942
1901
  if (!swiper.support.smoothScroll) {
1943
1902
  animateCSSModeScroll({
@@ -1955,10 +1914,7 @@
1955
1914
  return true;
1956
1915
  }
1957
1916
  const browser = getBrowser();
1958
- const isSafari = browser.isSafari;
1959
- if (isVirtual && !initial && isSafari && swiper.isElement) {
1960
- swiper.virtual.update(false, false, slideIndex);
1961
- }
1917
+ browser.isSafari;
1962
1918
  swiper.setTransition(speed);
1963
1919
  swiper.setTranslate(translate);
1964
1920
  swiper.updateActiveIndex(slideIndex);
@@ -2129,8 +2085,6 @@
2129
2085
  if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
2130
2086
  const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
2131
2087
  const swiperTranslate = JSON.parse(JSON.stringify(swiper.snapGrid[1]));
2132
-
2133
- // Move last item to first position only if active slide is the first slide
2134
2088
  const lastSlide = slides[slides.length - 1];
2135
2089
  lastSlide.swiperLoopMoveDOM = true;
2136
2090
  swiper.slidesEl.prepend(lastSlide);
@@ -2165,11 +2119,8 @@
2165
2119
  perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
2166
2120
  }
2167
2121
  const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup;
2168
- const isVirtual = swiper.virtual && params.virtual.enabled;
2169
2122
  if (params.loop) {
2170
- if (animating && !isVirtual && params.loopPreventsSliding) return false;
2171
-
2172
- // Kiểm tra xem loop có bị disable không
2123
+ if (animating && params.loopPreventsSliding) return false;
2173
2124
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
2174
2125
  if (swiper.slides.length >= currentSlidesPerView) {
2175
2126
  swiper.loopFix({
@@ -2196,7 +2147,6 @@
2196
2147
  const gap = Math.abs(swiper.snapGrid[lastSnapGridIndex] - swiper.snapGrid[lastSnapGridIndex - 1]);
2197
2148
  const swiperTranslate = structuredClone(swiper.snapGrid[lastSnapGridIndex - 1]);
2198
2149
  if (!swiper.params.loop) return;
2199
- // Move first item to last position only if active slide is the last slide
2200
2150
  const firstSlide = slides[0];
2201
2151
  firstSlide.swiperLoopMoveDOM = true;
2202
2152
  swiper.slidesEl.append(firstSlide);
@@ -2221,17 +2171,14 @@
2221
2171
  params,
2222
2172
  snapGrid,
2223
2173
  slidesGrid,
2224
- rtlTranslate,
2225
- enabled,
2226
- animating
2174
+ rtlTranslate: rtlTranslate,
2175
+ enabled
2227
2176
  } = swiper;
2228
2177
  if (!enabled || swiper.destroyed) return swiper;
2229
2178
  if (typeof speed === 'undefined') {
2230
2179
  speed = swiper.params.speed;
2231
2180
  }
2232
- swiper.virtual && params.virtual.enabled;
2233
2181
  if (params.loop) {
2234
- // Kiểm tra xem loop có bị disable không
2235
2182
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
2236
2183
  if (swiper.slides.length >= currentSlidesPerView) {
2237
2184
  swiper.loopFix({
@@ -2248,18 +2195,16 @@
2248
2195
  }
2249
2196
  const normalizedTranslate = normalize(translate);
2250
2197
  const normalizedSnapGrid = snapGrid.map(val => normalize(val));
2251
- const isFreeMode = params.freeMode && params.freeMode.enabled;
2252
2198
  let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
2253
- if (typeof prevSnap === 'undefined' && (params.cssMode || isFreeMode)) {
2199
+ if (typeof prevSnap === 'undefined' && params.cssMode) {
2254
2200
  let prevSnapIndex;
2255
2201
  snapGrid.forEach((snap, snapIndex) => {
2256
2202
  if (normalizedTranslate >= snap) {
2257
- // prevSnap = snap;
2258
2203
  prevSnapIndex = snapIndex;
2259
2204
  }
2260
2205
  });
2261
2206
  if (typeof prevSnapIndex !== 'undefined') {
2262
- prevSnap = isFreeMode ? snapGrid[prevSnapIndex] : snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];
2207
+ prevSnap = snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];
2263
2208
  }
2264
2209
  }
2265
2210
  let prevIndex = 0;
@@ -2272,7 +2217,7 @@
2272
2217
  }
2273
2218
  }
2274
2219
  if (params.rewind && swiper.isBeginning) {
2275
- const lastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;
2220
+ const lastIndex = swiper.slides.length - 1;
2276
2221
  return swiper.slideTo(lastIndex, speed, runCallbacks, internal);
2277
2222
  } else if (params.loop && swiper.activeIndex === 0 && params.cssMode) {
2278
2223
  requestAnimationFrame(() => {
@@ -2286,8 +2231,6 @@
2286
2231
  if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
2287
2232
  const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
2288
2233
  const swiperTranslate = JSON.parse(JSON.stringify(swiper.snapGrid[1]));
2289
-
2290
- // Move last item to first position only if active slide is the first slide
2291
2234
  if (!swiper.params.loop) return;
2292
2235
  const lastSlide = slides[slides.length - 1];
2293
2236
  lastSlide.swiperLoopMoveDOM = true;
@@ -2364,20 +2307,19 @@
2364
2307
  slidesEl
2365
2308
  } = swiper;
2366
2309
  const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
2367
- let slideToIndex = swiper.getSlideIndexWhenGrid(swiper.clickedIndex);
2310
+ const slideToIndex = swiper.clickedIndex;
2368
2311
  let realIndex;
2369
2312
  const slideSelector = swiper.isElement ? `swiper-slide` : `.${params.slideClass}`;
2370
- const isGrid = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
2371
2313
  if (params.loop) {
2372
2314
  if (swiper.animating) return;
2373
2315
  realIndex = parseInt(swiper.clickedSlide.getAttribute('data-swiper-slide-index'), 10);
2374
2316
  if (params.centeredSlides) {
2375
2317
  swiper.slideToLoop(realIndex);
2376
- } else if (slideToIndex > (isGrid ? (swiper.slides.length - slidesPerView) / 2 - (swiper.params.grid.rows - 1) : swiper.slides.length - slidesPerView)) {
2318
+ } else if (slideToIndex > swiper.slides.length - slidesPerView) {
2377
2319
  swiper.loopFix();
2378
- slideToIndex = swiper.getSlideIndex(elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0]);
2320
+ const clickedEl = elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0];
2379
2321
  nextTick(() => {
2380
- swiper.slideTo(slideToIndex);
2322
+ if (clickedEl) swiper.slideTo(swiper.getSlideIndex(clickedEl));
2381
2323
  });
2382
2324
  } else {
2383
2325
  swiper.slideTo(slideToIndex);
@@ -2404,7 +2346,7 @@
2404
2346
  params,
2405
2347
  slidesEl
2406
2348
  } = swiper;
2407
- if (!params.loop || swiper.virtual && swiper.params.virtual.enabled) return;
2349
+ if (!params.loop) return;
2408
2350
  const initSlides = () => {
2409
2351
  const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`);
2410
2352
  slides.forEach((el, index) => {
@@ -2413,21 +2355,17 @@
2413
2355
  };
2414
2356
  const clearBlankSlides = () => {
2415
2357
  const slides = elementChildren(slidesEl, `.${params.slideBlankClass}`);
2416
- slides.forEach(el => {
2417
- el.remove();
2418
- });
2358
+ slides.forEach(el => el.remove());
2419
2359
  if (slides.length > 0) {
2420
2360
  swiper.recalcSlides();
2421
2361
  swiper.updateSlides();
2422
2362
  }
2423
2363
  };
2424
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
2425
- if (params.loopAddBlankSlides && (params.slidesPerGroup > 1 || gridEnabled)) {
2364
+ if (params.loopAddBlankSlides && params.slidesPerGroup > 1) {
2426
2365
  clearBlankSlides();
2427
2366
  }
2428
- const slidesPerGroup = params.slidesPerGroup * (gridEnabled ? params.grid.rows : 1);
2367
+ const slidesPerGroup = params.slidesPerGroup;
2429
2368
  const shouldFillGroup = swiper.slides.length % slidesPerGroup !== 0;
2430
- const shouldFillGrid = gridEnabled && swiper.slides.length % params.grid.rows !== 0;
2431
2369
  const addBlankSlides = amountOfSlides => {
2432
2370
  for (let i = 0; i < amountOfSlides; i += 1) {
2433
2371
  const slideEl = swiper.isElement ? createElement('swiper-slide', [params.slideBlankClass]) : createElement('div', [params.slideClass, params.slideBlankClass]);
@@ -2444,16 +2382,6 @@
2444
2382
  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)');
2445
2383
  }
2446
2384
  initSlides();
2447
- } else if (shouldFillGrid) {
2448
- if (params.loopAddBlankSlides) {
2449
- const slidesToAdd = params.grid.rows - swiper.slides.length % params.grid.rows;
2450
- addBlankSlides(slidesToAdd);
2451
- swiper.recalcSlides();
2452
- swiper.updateSlides();
2453
- } else {
2454
- 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)');
2455
- }
2456
- initSlides();
2457
2385
  } else {
2458
2386
  initSlides();
2459
2387
  }
@@ -2472,13 +2400,12 @@
2472
2400
  setTranslate,
2473
2401
  activeSlideIndex,
2474
2402
  initial,
2475
- byController,
2476
2403
  byMousewheel
2477
2404
  } = _temp === void 0 ? {} : _temp;
2478
2405
  const swiper = this;
2479
2406
  if (!swiper.params.loop) return;
2480
2407
 
2481
- // Disable loop mode nếu số slides ít hơn slidesPerView
2408
+ // Disable loop mode if number of slides is smaller than slidesPerView
2482
2409
  const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2483
2410
  if (swiper.slides.length < currentSlidesPerView) {
2484
2411
  console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
@@ -2498,21 +2425,6 @@
2498
2425
  } = params;
2499
2426
  swiper.allowSlidePrev = true;
2500
2427
  swiper.allowSlideNext = true;
2501
- if (swiper.virtual && params.virtual.enabled) {
2502
- if (slideTo) {
2503
- if (!params.centeredSlides && swiper.snapIndex === 0) {
2504
- swiper.slideTo(swiper.virtual.slides.length, 0, false, true);
2505
- } else if (params.centeredSlides && swiper.snapIndex < params.slidesPerView) {
2506
- swiper.slideTo(swiper.virtual.slides.length + swiper.snapIndex, 0, false, true);
2507
- } else if (swiper.snapIndex === swiper.snapGrid.length - 1) {
2508
- swiper.slideTo(swiper.virtual.slidesBefore, 0, false, true);
2509
- }
2510
- }
2511
- swiper.allowSlidePrev = allowSlidePrev;
2512
- swiper.allowSlideNext = allowSlideNext;
2513
- swiper.emit('loopFix');
2514
- return;
2515
- }
2516
2428
  let slidesPerView = params.slidesPerView;
2517
2429
  if (slidesPerView === 'auto') {
2518
2430
  slidesPerView = swiper.slidesPerViewDynamic();
@@ -2522,22 +2434,19 @@
2522
2434
  slidesPerView = slidesPerView + 1;
2523
2435
  }
2524
2436
  }
2525
- const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup;
2437
+ const slidesPerGroup = params.slidesPerGroup;
2526
2438
  let loopedSlides = centeredSlides ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) : slidesPerGroup;
2527
2439
  if (loopedSlides % slidesPerGroup !== 0) {
2528
2440
  loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup;
2529
2441
  }
2530
2442
  loopedSlides += params.loopAdditionalSlides;
2531
2443
  swiper.loopedSlides = loopedSlides;
2532
- const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
2533
- if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2444
+ if (slides.length < slidesPerView + loopedSlides) {
2534
2445
  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');
2535
- } else if (gridEnabled && params.grid.fill === 'row') {
2536
- showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
2537
2446
  }
2538
2447
  const prependSlidesIndexes = [];
2539
2448
  const appendSlidesIndexes = [];
2540
- const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length;
2449
+ const cols = slides.length;
2541
2450
  const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !centeredSlides;
2542
2451
  let activeIndex = isInitialOverflow ? initialSlide : swiper.activeIndex;
2543
2452
  if (typeof activeSlideIndex === 'undefined') {
@@ -2549,24 +2458,15 @@
2549
2458
  const isPrev = direction === 'prev' || !direction;
2550
2459
  let slidesPrepended = 0;
2551
2460
  let slidesAppended = 0;
2552
- const activeColIndex = gridEnabled ? slides[activeSlideIndex].column : activeSlideIndex;
2461
+ const activeColIndex = activeSlideIndex;
2553
2462
  const activeColIndexWithShift = activeColIndex + (centeredSlides && typeof setTranslate === 'undefined' ? -slidesPerView / 2 + 0.5 : 0);
2463
+
2554
2464
  // prepend last slides before start
2555
2465
  if (activeColIndexWithShift < loopedSlides) {
2556
2466
  slidesPrepended = Math.max(loopedSlides - activeColIndexWithShift, slidesPerGroup);
2557
2467
  for (let i = 0; i < loopedSlides - activeColIndexWithShift; i += 1) {
2558
2468
  const index = i - Math.floor(i / cols) * cols;
2559
- if (gridEnabled) {
2560
- const colIndexToPrepend = cols - index - 1;
2561
- for (let i = slides.length - 1; i >= 0; i -= 1) {
2562
- if (slides[i].column === colIndexToPrepend) prependSlidesIndexes.push(i);
2563
- }
2564
- // slides.forEach((slide, slideIndex) => {
2565
- // if (slide.column === colIndexToPrepend) prependSlidesIndexes.push(slideIndex);
2566
- // });
2567
- } else {
2568
- prependSlidesIndexes.push(cols - index - 1);
2569
- }
2469
+ prependSlidesIndexes.push(cols - index - 1);
2570
2470
  }
2571
2471
  } else if (activeColIndexWithShift + slidesPerView > cols - loopedSlides) {
2572
2472
  slidesAppended = Math.max(activeColIndexWithShift - (cols - loopedSlides * 2), slidesPerGroup);
@@ -2575,27 +2475,13 @@
2575
2475
  }
2576
2476
  for (let i = 0; i < slidesAppended; i += 1) {
2577
2477
  const index = i - Math.floor(i / cols) * cols;
2578
- if (gridEnabled) {
2579
- slides.forEach((slide, slideIndex) => {
2580
- if (slide.column === index) appendSlidesIndexes.push(slideIndex);
2581
- });
2582
- } else {
2583
- appendSlidesIndexes.push(index);
2584
- }
2478
+ appendSlidesIndexes.push(index);
2585
2479
  }
2586
2480
  }
2587
2481
  swiper.__preventObserver__ = true;
2588
2482
  requestAnimationFrame(() => {
2589
2483
  swiper.__preventObserver__ = false;
2590
2484
  });
2591
- if (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2592
- if (appendSlidesIndexes.includes(activeSlideIndex)) {
2593
- appendSlidesIndexes.splice(appendSlidesIndexes.indexOf(activeSlideIndex), 1);
2594
- }
2595
- if (prependSlidesIndexes.includes(activeSlideIndex)) {
2596
- prependSlidesIndexes.splice(prependSlidesIndexes.indexOf(activeSlideIndex), 1);
2597
- }
2598
- }
2599
2485
  if (isPrev) {
2600
2486
  prependSlidesIndexes.forEach(index => {
2601
2487
  slides[index].swiperLoopMoveDOM = true;
@@ -2613,13 +2499,11 @@
2613
2499
  swiper.recalcSlides();
2614
2500
  if (params.slidesPerView === 'auto') {
2615
2501
  swiper.updateSlides();
2616
- } else if (gridEnabled && (prependSlidesIndexes.length > 0 && isPrev || appendSlidesIndexes.length > 0 && isNext)) {
2617
- swiper.slides.forEach((slide, slideIndex) => {
2618
- swiper.grid.updateSlide(slideIndex, slide, swiper.slides);
2619
- });
2620
2502
  }
2621
2503
  if (params.watchSlidesProgress) {
2622
- swiper.updateSlidesOffset();
2504
+ swiper.updateSlidesOffset({
2505
+ isCalculatedFromUpdateSlides: params.slidesPerView === 'auto'
2506
+ });
2623
2507
  }
2624
2508
  if (slideTo) {
2625
2509
  if (prependSlidesIndexes.length > 0 && isPrev) {
@@ -2636,12 +2520,10 @@
2636
2520
  swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff;
2637
2521
  }
2638
2522
  }
2639
- } else {
2640
- if (setTranslate) {
2641
- const shift = gridEnabled ? prependSlidesIndexes.length / params.grid.rows : prependSlidesIndexes.length;
2642
- swiper.slideTo(swiper.activeIndex + shift, 0, false, true);
2643
- swiper.touchEventsData.currentTranslate = swiper.translate;
2644
- }
2523
+ } else if (setTranslate) {
2524
+ const shift = prependSlidesIndexes.length;
2525
+ swiper.slideTo(swiper.activeIndex + shift, 0, false, true);
2526
+ swiper.touchEventsData.currentTranslate = swiper.translate;
2645
2527
  }
2646
2528
  } else if (appendSlidesIndexes.length > 0 && isNext) {
2647
2529
  if (typeof slideRealIndex === 'undefined') {
@@ -2657,36 +2539,14 @@
2657
2539
  swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff;
2658
2540
  }
2659
2541
  }
2660
- } else {
2661
- const shift = gridEnabled ? appendSlidesIndexes.length / params.grid.rows : appendSlidesIndexes.length;
2542
+ } else if (setTranslate) {
2543
+ const shift = appendSlidesIndexes.length;
2662
2544
  swiper.slideTo(swiper.activeIndex - shift, 0, false, true);
2663
2545
  }
2664
2546
  }
2665
2547
  }
2666
2548
  swiper.allowSlidePrev = allowSlidePrev;
2667
2549
  swiper.allowSlideNext = allowSlideNext;
2668
- if (swiper.controller && swiper.controller.control && !byController) {
2669
- const loopParams = {
2670
- slideRealIndex,
2671
- direction,
2672
- setTranslate,
2673
- activeSlideIndex,
2674
- byController: true
2675
- };
2676
- if (Array.isArray(swiper.controller.control)) {
2677
- swiper.controller.control.forEach(c => {
2678
- if (!c.destroyed && c.params.loop) c.loopFix({
2679
- ...loopParams,
2680
- slideTo: c.params.slidesPerView === params.slidesPerView ? slideTo : false
2681
- });
2682
- });
2683
- } else if (swiper.controller.control instanceof swiper.constructor && swiper.controller.control.params.loop) {
2684
- swiper.controller.control.loopFix({
2685
- ...loopParams,
2686
- slideTo: swiper.controller.control.params.slidesPerView === params.slidesPerView ? slideTo : false
2687
- });
2688
- }
2689
- }
2690
2550
  swiper.emit('loopFix');
2691
2551
  }
2692
2552
 
@@ -2703,7 +2563,7 @@
2703
2563
  const swiper = this;
2704
2564
  if (!swiper.params.loop) return;
2705
2565
 
2706
- // Disable loop mode nếu số slides ít hơn slidesPerView
2566
+ // Disable loop mode if number of slides is smaller than slidesPerView
2707
2567
  const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2708
2568
  if (swiper.slides.length < currentSlidesPerView) {
2709
2569
  console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
@@ -2742,7 +2602,7 @@
2742
2602
  }
2743
2603
  loopedSlides += params.loopAdditionalSlides;
2744
2604
  swiper.loopedSlides = loopedSlides;
2745
- if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2605
+ if (slides.length < slidesPerView + loopedSlides) {
2746
2606
  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');
2747
2607
  }
2748
2608
  const isNext = direction === 'next' || !direction;
@@ -2768,20 +2628,16 @@
2768
2628
  activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass)));
2769
2629
  }
2770
2630
 
2771
- // Tạo DocumentFragment để chứa các slide clone
2631
+ // DocumentFragment to hold slide clones
2772
2632
  const cloneFragment = document.createDocumentFragment();
2773
2633
 
2774
- // Clone các slide theo numberOfSlidesNeedClone (đã đảo ngược) và thêm vào fragment
2634
+ // Clone slides according to numberOfSlidesNeedClone and append to fragment
2775
2635
  (isNext ? numberOfSlidesNeedClone : numberOfSlidesNeedClone.reverse()).forEach(index => {
2776
2636
  if (slides[index]) {
2777
2637
  const originalSlide = slides[index];
2778
2638
  const clonedSlide = originalSlide.cloneNode(true);
2779
-
2780
- // Đánh dấu slide clone
2781
2639
  clonedSlide.setAttribute('data-swiper-clone', 'true');
2782
2640
  clonedSlide.classList.add('swiper-slide-clone');
2783
-
2784
- // Thêm clone vào fragment
2785
2641
  cloneFragment.appendChild(clonedSlide);
2786
2642
  }
2787
2643
  });
@@ -2802,32 +2658,28 @@
2802
2658
  });
2803
2659
  }
2804
2660
 
2805
- // Sắp xếp cloneFragment theo data-swiper-slide-index tăng dần
2661
+ // Sort cloned slides by data-swiper-slide-index
2806
2662
  const clonedSlides = Array.from(cloneFragment.children);
2807
2663
  clonedSlides.sort((a, b) => {
2808
2664
  const indexA = parseInt(a.getAttribute('data-swiper-slide-index')) || 0;
2809
2665
  const indexB = parseInt(b.getAttribute('data-swiper-slide-index')) || 0;
2810
2666
  return indexA - indexB;
2811
2667
  });
2812
-
2813
- // Xóa tất cả children cũ và thêm lại theo thứ tự đã sắp xếp
2814
2668
  cloneFragment.innerHTML = '';
2815
2669
  clonedSlides.forEach(slide => {
2816
2670
  cloneFragment.appendChild(slide);
2817
2671
  });
2818
2672
 
2819
- // Thêm fragment vào vị trí phù hợp
2673
+ // Place fragment into the right position
2820
2674
  if (isPrev) {
2821
- // Nếu là prev, thêm fragment vào cuối slidesEl
2822
2675
  slidesEl.appendChild(cloneFragment);
2823
2676
  } else if (isNext) {
2824
- // Nếu là next, thêm fragment vào đầu slidesEl
2825
2677
  slidesEl.insertBefore(cloneFragment, slidesEl.firstChild);
2826
2678
  }
2827
2679
  swiper.recalcSlides();
2828
2680
  swiper.updateSlides();
2829
2681
 
2830
- // Tìm slide data-swiper-slide-index tương ứng
2682
+ // Find old active slide index after recalculation
2831
2683
  let oldActiveIndex = null;
2832
2684
  for (let i = 0; i < slidesEl.children.length; i++) {
2833
2685
  const child = slidesEl.children[i];
@@ -2840,7 +2692,7 @@
2840
2692
  swiper.slideTo(oldActiveIndex, 0);
2841
2693
  }
2842
2694
 
2843
- // Tìm vị trí slide sau khi remove clone để set lại translate tạo hiệu ứng animate
2695
+ // Update translate after removing clones for animation
2844
2696
  const skip = Math.min(swiper.params.slidesPerGroupSkip, newIndex);
2845
2697
  let snapIndex = skip + Math.floor((newIndex - skip) / swiper.params.slidesPerGroup);
2846
2698
  if (snapIndex >= swiper.snapGrid.length) snapIndex = swiper.snapGrid.length - 1;
@@ -2866,7 +2718,8 @@
2866
2718
  }
2867
2719
  swiper.setTranslate(updateTranslate);
2868
2720
  }
2869
- // Remove slide clone ra khỏi slidesEl sau khi slideTo hoàn thành
2721
+
2722
+ // Remove clones
2870
2723
  const cloneSlides = slidesEl.querySelectorAll('[data-swiper-clone="true"]');
2871
2724
  cloneSlides.forEach(cloneSlide => {
2872
2725
  if (cloneSlide.parentNode) {
@@ -2896,7 +2749,7 @@
2896
2749
  params,
2897
2750
  slidesEl
2898
2751
  } = swiper;
2899
- if (!params.loop || !slidesEl || swiper.virtual && swiper.params.virtual.enabled) return;
2752
+ if (!params.loop || !slidesEl) return;
2900
2753
  swiper.recalcSlides();
2901
2754
  const newSlidesOrder = [];
2902
2755
  swiper.slides.forEach(slideEl => {
@@ -2957,7 +2810,6 @@
2957
2810
  unsetGrabCursor
2958
2811
  };
2959
2812
 
2960
- // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd
2961
2813
  function closestElement(selector, base) {
2962
2814
  if (base === void 0) {
2963
2815
  base = this;
@@ -2966,9 +2818,7 @@
2966
2818
  if (!el || el === getDocument() || el === getWindow()) return null;
2967
2819
  if (el.assignedSlot) el = el.assignedSlot;
2968
2820
  const found = el.closest(selector);
2969
- if (!found && !el.getRootNode) {
2970
- return null;
2971
- }
2821
+ if (!found && !el.getRootNode) return null;
2972
2822
  return found || __closestFrom(el.getRootNode().host);
2973
2823
  }
2974
2824
  return __closestFrom(base);
@@ -2996,9 +2846,7 @@
2996
2846
  if (e.originalEvent) e = e.originalEvent;
2997
2847
  const data = swiper.touchEventsData;
2998
2848
  if (e.type === 'pointerdown') {
2999
- if (data.pointerId !== null && data.pointerId !== e.pointerId) {
3000
- return;
3001
- }
2849
+ if (data.pointerId !== null && data.pointerId !== e.pointerId) return;
3002
2850
  data.pointerId = e.pointerId;
3003
2851
  } else if (e.type === 'touchstart' && e.targetTouches.length === 1) {
3004
2852
  data.touchId = e.targetTouches[0].identifier;
@@ -3015,9 +2863,7 @@
3015
2863
  } = swiper;
3016
2864
  if (!enabled) return;
3017
2865
  if (!params.simulateTouch && e.pointerType === 'mouse') return;
3018
- if (swiper.animating && params.preventInteractionOnTransition) {
3019
- return;
3020
- }
2866
+ if (swiper.animating && params.preventInteractionOnTransition) return;
3021
2867
  if (!swiper.animating && params.cssMode && params.loop) {
3022
2868
  swiper.loopFix();
3023
2869
  }
@@ -3028,8 +2874,6 @@
3028
2874
  if ('which' in e && e.which === 3) return;
3029
2875
  if ('button' in e && e.button > 0) return;
3030
2876
  if (data.isTouched && data.isMoved) return;
3031
-
3032
- // change target el for shadow root component
3033
2877
  const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';
3034
2878
  // eslint-disable-next-line
3035
2879
  const eventPath = e.composedPath ? e.composedPath() : e.path;
@@ -3038,8 +2882,6 @@
3038
2882
  }
3039
2883
  const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;
3040
2884
  const isTargetShadow = !!(e.target && e.target.shadowRoot);
3041
-
3042
- // use closestElement for shadow root element to get the actual closest for nested shadow root element
3043
2885
  if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, targetEl) : targetEl.closest(noSwipingSelector))) {
3044
2886
  swiper.allowClick = true;
3045
2887
  return;
@@ -3051,12 +2893,7 @@
3051
2893
  touches.currentY = e.pageY;
3052
2894
  const startX = touches.currentX;
3053
2895
  const startY = touches.currentY;
3054
-
3055
- // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore
3056
-
3057
- if (!preventEdgeSwipe(swiper, e, startX)) {
3058
- return;
3059
- }
2896
+ if (!preventEdgeSwipe(swiper, e, startX)) return;
3060
2897
  Object.assign(data, {
3061
2898
  isTouched: true,
3062
2899
  isMoved: false,
@@ -3085,9 +2922,6 @@
3085
2922
  if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !targetEl.isContentEditable) {
3086
2923
  e.preventDefault();
3087
2924
  }
3088
- if (params.freeMode && params.freeMode.enabled && swiper.freeMode && swiper.animating && !params.cssMode) {
3089
- swiper.freeMode.onTouchStart();
3090
- }
3091
2925
  swiper.emit('touchStart', e);
3092
2926
  }
3093
2927
 
@@ -3106,7 +2940,7 @@
3106
2940
  let e = event;
3107
2941
  if (e.originalEvent) e = e.originalEvent;
3108
2942
  if (e.type === 'pointermove') {
3109
- if (data.touchId !== null) return; // return from pointer if we use touch
2943
+ if (data.touchId !== null) return;
3110
2944
  const id = e.pointerId;
3111
2945
  if (id !== data.pointerId) return;
3112
2946
  }
@@ -3147,7 +2981,6 @@
3147
2981
  }
3148
2982
  if (params.touchReleaseOnEdges && !params.loop) {
3149
2983
  if (swiper.isVertical()) {
3150
- // Vertical
3151
2984
  if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) {
3152
2985
  data.isTouched = false;
3153
2986
  data.isMoved = false;
@@ -3249,7 +3082,6 @@
3249
3082
  swiper.wrapperEl.dispatchEvent(evt);
3250
3083
  }
3251
3084
  data.allowMomentumBounce = false;
3252
- // Grab Cursor
3253
3085
  if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
3254
3086
  swiper.setGrabCursor(true);
3255
3087
  }
@@ -3320,8 +3152,6 @@
3320
3152
  if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {
3321
3153
  data.currentTranslate = data.startTranslate;
3322
3154
  }
3323
-
3324
- // Threshold
3325
3155
  if (params.threshold > 0) {
3326
3156
  if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
3327
3157
  if (!data.allowThresholdMove) {
@@ -3339,17 +3169,12 @@
3339
3169
  }
3340
3170
  if (!params.followFinger || params.cssMode) return;
3341
3171
 
3342
- // Update active index in free mode
3343
- if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {
3172
+ // core-lite: no optional feature updates; only watchSlidesProgress
3173
+ if (params.watchSlidesProgress) {
3344
3174
  swiper.updateActiveIndex();
3345
3175
  swiper.updateSlidesClasses();
3346
3176
  }
3347
- if (params.freeMode && params.freeMode.enabled && swiper.freeMode) {
3348
- swiper.freeMode.onTouchMove();
3349
- }
3350
- // Update progress
3351
3177
  swiper.updateProgress(data.currentTranslate);
3352
- // Update translate
3353
3178
  swiper.setTranslate(data.currentTranslate);
3354
3179
  }
3355
3180
 
@@ -3361,7 +3186,7 @@
3361
3186
  let targetTouch;
3362
3187
  const isTouchEvent = e.type === 'touchend' || e.type === 'touchcancel';
3363
3188
  if (!isTouchEvent) {
3364
- if (data.touchId !== null) return; // return from pointer if we use touch
3189
+ if (data.touchId !== null) return;
3365
3190
  if (e.pointerId !== data.pointerId) return;
3366
3191
  targetTouch = e;
3367
3192
  } else {
@@ -3370,9 +3195,7 @@
3370
3195
  }
3371
3196
  if (['pointercancel', 'pointerout', 'pointerleave', 'contextmenu'].includes(e.type)) {
3372
3197
  const proceed = ['pointercancel', 'contextmenu'].includes(e.type) && (swiper.browser.isSafari || swiper.browser.isWebView);
3373
- if (!proceed) {
3374
- return;
3375
- }
3198
+ if (!proceed) return;
3376
3199
  }
3377
3200
  data.pointerId = null;
3378
3201
  data.touchId = null;
@@ -3390,9 +3213,7 @@
3390
3213
  }
3391
3214
  data.allowTouchCallbacks = false;
3392
3215
  if (!data.isTouched) {
3393
- if (data.isMoved && params.grabCursor) {
3394
- swiper.setGrabCursor(false);
3395
- }
3216
+ if (data.isMoved && params.grabCursor) swiper.setGrabCursor(false);
3396
3217
  data.isMoved = false;
3397
3218
  data.startMoving = false;
3398
3219
  return;
@@ -3402,8 +3223,6 @@
3402
3223
  if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
3403
3224
  swiper.setGrabCursor(false);
3404
3225
  }
3405
-
3406
- // Time diff
3407
3226
  const touchEndTime = now();
3408
3227
  const timeDiff = touchEndTime - data.touchStartTime;
3409
3228
 
@@ -3430,20 +3249,8 @@
3430
3249
  data.isMoved = false;
3431
3250
  data.startMoving = false;
3432
3251
  let currentPos;
3433
- if (params.followFinger) {
3434
- currentPos = rtl ? swiper.translate : -swiper.translate;
3435
- } else {
3436
- currentPos = -data.currentTranslate;
3437
- }
3438
- if (params.cssMode) {
3439
- return;
3440
- }
3441
- if (params.freeMode && params.freeMode.enabled) {
3442
- swiper.freeMode.onTouchEnd({
3443
- currentPos
3444
- });
3445
- return;
3446
- }
3252
+ if (params.followFinger) currentPos = rtl ? swiper.translate : -swiper.translate;else currentPos = -data.currentTranslate;
3253
+ if (params.cssMode) return;
3447
3254
 
3448
3255
  // Find current slide
3449
3256
  const swipeToLast = currentPos >= -swiper.maxTranslate() && !swiper.params.loop;
@@ -3465,22 +3272,22 @@
3465
3272
  let rewindLastIndex = null;
3466
3273
  if (params.rewind) {
3467
3274
  if (swiper.isBeginning) {
3468
- rewindLastIndex = params.virtual && params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;
3275
+ rewindLastIndex = swiper.slides.length - 1;
3469
3276
  } else if (swiper.isEnd) {
3470
3277
  rewindFirstIndex = 0;
3471
3278
  }
3472
3279
  }
3473
- // Find current slide size
3474
3280
  const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
3475
3281
  const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
3476
3282
  if (timeDiff > params.longSwipesMs) {
3477
- // Long touches
3478
3283
  if (!params.longSwipes) {
3479
3284
  swiper.slideTo(swiper.activeIndex);
3480
3285
  return;
3481
3286
  }
3482
3287
  if (swiper.swipeDirection === 'next') {
3483
- if (ratio >= params.longSwipesRatio) swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);else swiper.slideTo(stopIndex);
3288
+ if (ratio >= params.longSwipesRatio) {
3289
+ swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);
3290
+ } else swiper.slideTo(stopIndex);
3484
3291
  }
3485
3292
  if (swiper.swipeDirection === 'prev') {
3486
3293
  if (ratio > 1 - params.longSwipesRatio) {
@@ -3532,7 +3339,6 @@
3532
3339
  allowSlidePrev,
3533
3340
  snapGrid
3534
3341
  } = swiper;
3535
- const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
3536
3342
 
3537
3343
  // Disable locks on resize
3538
3344
  swiper.allowSlideNext = true;
@@ -3540,15 +3346,12 @@
3540
3346
  swiper.updateSize();
3541
3347
  swiper.updateSlides();
3542
3348
  swiper.updateSlidesClasses();
3543
- const isVirtualLoop = isVirtual && params.loop;
3544
- if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides && !isVirtualLoop) {
3349
+ if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides) {
3545
3350
  swiper.slideTo(swiper.slides.length - 1, 0, false, true);
3351
+ } else if (swiper.params.loop) {
3352
+ swiper.slideToLoop(swiper.realIndex, 0, false, true);
3546
3353
  } else {
3547
- if (swiper.params.loop && !isVirtual) {
3548
- swiper.slideToLoop(swiper.realIndex, 0, false, true);
3549
- } else {
3550
- swiper.slideTo(swiper.activeIndex, 0, false, true);
3551
- }
3354
+ swiper.slideTo(swiper.activeIndex, 0, false, true);
3552
3355
  }
3553
3356
  if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
3554
3357
  clearTimeout(swiper.autoplay.resizeTimeout);
@@ -3558,10 +3361,11 @@
3558
3361
  }
3559
3362
  }, 500);
3560
3363
  }
3364
+
3561
3365
  // Return locks after resize
3562
3366
  swiper.allowSlidePrev = allowSlidePrev;
3563
3367
  swiper.allowSlideNext = allowSlideNext;
3564
- if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
3368
+ if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
3565
3369
  swiper.checkOverflow();
3566
3370
  }
3567
3371
  }
@@ -3615,6 +3419,10 @@
3615
3419
  if (swiper.params.cssMode || swiper.params.slidesPerView !== 'auto' && !swiper.params.autoHeight) {
3616
3420
  return;
3617
3421
  }
3422
+ const el = e?.target;
3423
+ // IMG, IFRAME, EMBED with width/height attributes don't change slide size — no need to call swiper.update()
3424
+ if (!el || !['IMG', 'IFRAME', 'EMBED'].includes(el.tagName)) return;
3425
+ if (el.hasAttribute('width') && el.hasAttribute('height')) return;
3618
3426
  swiper.update();
3619
3427
  }
3620
3428
 
@@ -3726,8 +3534,15 @@
3726
3534
  detachEvents
3727
3535
  };
3728
3536
 
3729
- const isGridEnabled = (swiper, params) => {
3730
- return swiper.grid && params.grid && params.grid.rows > 1;
3537
+ const toggleModule = (swiper, params, breakpointParams, prop) => {
3538
+ const wasModuleEnabled = params[prop] && params[prop].enabled;
3539
+ const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled;
3540
+ if (wasModuleEnabled && !isModuleEnabled) {
3541
+ swiper[prop].disable();
3542
+ }
3543
+ if (!wasModuleEnabled && isModuleEnabled) {
3544
+ swiper[prop].enable();
3545
+ }
3731
3546
  };
3732
3547
  function setBreakpoint() {
3733
3548
  const swiper = this;
@@ -3748,38 +3563,20 @@
3748
3563
  if (!breakpoint || swiper.currentBreakpoint === breakpoint) return;
3749
3564
  const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
3750
3565
  const breakpointParams = breakpointOnlyParams || swiper.originalParams;
3751
- const wasMultiRow = isGridEnabled(swiper, params);
3752
- const isMultiRow = isGridEnabled(swiper, breakpointParams);
3753
3566
  const wasGrabCursor = swiper.params.grabCursor;
3754
3567
  const isGrabCursor = breakpointParams.grabCursor;
3755
3568
  const wasEnabled = params.enabled;
3756
- if (wasMultiRow && !isMultiRow) {
3757
- el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
3758
- swiper.emitContainerClasses();
3759
- } else if (!wasMultiRow && isMultiRow) {
3760
- el.classList.add(`${params.containerModifierClass}grid`);
3761
- if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') {
3762
- el.classList.add(`${params.containerModifierClass}grid-column`);
3763
- }
3764
- swiper.emitContainerClasses();
3765
- }
3766
3569
  if (wasGrabCursor && !isGrabCursor) {
3767
3570
  swiper.unsetGrabCursor();
3768
3571
  } else if (!wasGrabCursor && isGrabCursor) {
3769
3572
  swiper.setGrabCursor();
3770
3573
  }
3771
3574
 
3772
- // Toggle navigation, pagination, scrollbar
3773
- ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
3575
+ // Core-lite: toggle navigation & pagination only.
3576
+ const modules = ['navigation', 'pagination'];
3577
+ modules.forEach(prop => {
3774
3578
  if (typeof breakpointParams[prop] === 'undefined') return;
3775
- const wasModuleEnabled = params[prop] && params[prop].enabled;
3776
- const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled;
3777
- if (wasModuleEnabled && !isModuleEnabled) {
3778
- swiper[prop].disable();
3779
- }
3780
- if (!wasModuleEnabled && isModuleEnabled) {
3781
- swiper[prop].enable();
3782
- }
3579
+ toggleModule(swiper, params, breakpointParams, prop);
3783
3580
  });
3784
3581
  const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
3785
3582
  const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
@@ -3861,7 +3658,7 @@
3861
3658
  getBreakpoint
3862
3659
  };
3863
3660
 
3864
- function prepareClasses(entries, prefix) {
3661
+ const prepareClasses = (entries, prefix) => {
3865
3662
  const resultClasses = [];
3866
3663
  entries.forEach(item => {
3867
3664
  if (typeof item === 'object') {
@@ -3875,7 +3672,7 @@
3875
3672
  }
3876
3673
  });
3877
3674
  return resultClasses;
3878
- }
3675
+ };
3879
3676
  function addClasses() {
3880
3677
  const swiper = this;
3881
3678
  const {
@@ -3885,17 +3682,12 @@
3885
3682
  el,
3886
3683
  device
3887
3684
  } = swiper;
3685
+ // core-lite: removed module-specific classes
3888
3686
  // prettier-ignore
3889
3687
  const suffixes = prepareClasses(['initialized', params.direction, {
3890
- 'free-mode': swiper.params.freeMode && params.freeMode.enabled
3891
- }, {
3892
3688
  'autoheight': params.autoHeight
3893
3689
  }, {
3894
3690
  'rtl': rtl
3895
- }, {
3896
- 'grid': params.grid && params.grid.rows > 1
3897
- }, {
3898
- 'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'
3899
3691
  }, {
3900
3692
  'android': device.android
3901
3693
  }, {
@@ -3992,16 +3784,12 @@
3992
3784
  autoHeight: false,
3993
3785
  // Set wrapper width
3994
3786
  setWrapperSize: false,
3995
- // Virtual Translate
3996
- virtualTranslate: false,
3997
- // Effects
3787
+ // Effects (core-lite only supports `slide`)
3998
3788
  effect: 'slide',
3999
- // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
4000
-
4001
3789
  // Breakpoints
4002
3790
  breakpoints: undefined,
4003
3791
  breakpointsBase: 'window',
4004
- // Slides grid
3792
+ // Slides
4005
3793
  spaceBetween: 0,
4006
3794
  slidesPerView: 1,
4007
3795
  slidesPerGroup: 1,
@@ -4104,7 +3892,9 @@
4104
3892
  if (moduleParamName === 'navigation' && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].prevEl && !params[moduleParamName].nextEl) {
4105
3893
  params[moduleParamName].auto = true;
4106
3894
  }
4107
- if (['pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].el) {
3895
+
3896
+ // Core-lite: keep only pagination auto-init.
3897
+ if (moduleParamName === 'pagination' && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].el) {
4108
3898
  params[moduleParamName].auto = true;
4109
3899
  }
4110
3900
  if (!(moduleParamName in params && 'enabled' in moduleParams)) {
@@ -4230,7 +4020,6 @@
4230
4020
  // Indexes
4231
4021
  activeIndex: 0,
4232
4022
  realIndex: 0,
4233
- //
4234
4023
  isBeginning: true,
4235
4024
  isEnd: false,
4236
4025
  // Props
@@ -4257,12 +4046,9 @@
4257
4046
  currentTranslate: undefined,
4258
4047
  startTranslate: undefined,
4259
4048
  allowThresholdMove: undefined,
4260
- // Form elements to match
4261
4049
  focusableElements: swiper.params.focusableElements,
4262
- // Last click time
4263
4050
  lastClickTime: 0,
4264
4051
  clickTimeout: undefined,
4265
- // Velocities
4266
4052
  velocities: [],
4267
4053
  allowMomentumBounce: undefined,
4268
4054
  startMoving: undefined,
@@ -4282,7 +4068,8 @@
4282
4068
  },
4283
4069
  // Images
4284
4070
  imagesToLoad: [],
4285
- imagesLoaded: 0
4071
+ imagesLoaded: 0,
4072
+ rtl: params?.rtl
4286
4073
  });
4287
4074
  swiper.emit('_swiper');
4288
4075
 
@@ -4291,7 +4078,6 @@
4291
4078
  swiper.init();
4292
4079
  }
4293
4080
 
4294
- // Return app instance
4295
4081
  // eslint-disable-next-line no-constructor-return
4296
4082
  return swiper;
4297
4083
  }
@@ -4323,16 +4109,6 @@
4323
4109
  getSlideIndexByData(index) {
4324
4110
  return this.getSlideIndex(this.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === index));
4325
4111
  }
4326
- getSlideIndexWhenGrid(index) {
4327
- if (this.grid && this.params.grid && this.params.grid.rows > 1) {
4328
- if (this.params.grid.fill === 'column') {
4329
- index = Math.floor(index / this.params.grid.rows);
4330
- } else if (this.params.grid.fill === 'row') {
4331
- index = index % Math.ceil(this.slides.length / this.params.grid.rows);
4332
- }
4333
- }
4334
- return index;
4335
- }
4336
4112
  recalcSlides() {
4337
4113
  const swiper = this;
4338
4114
  const {
@@ -4434,21 +4210,15 @@
4434
4210
  }
4435
4211
  }
4436
4212
  } else {
4437
- // eslint-disable-next-line
4438
4213
  if (view === 'current') {
4439
4214
  for (let i = activeIndex + 1; i < slides.length; i += 1) {
4440
4215
  const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;
4441
- if (slideInView) {
4442
- spv += 1;
4443
- }
4216
+ if (slideInView) spv += 1;
4444
4217
  }
4445
4218
  } else {
4446
- // previous
4447
4219
  for (let i = activeIndex - 1; i >= 0; i -= 1) {
4448
4220
  const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;
4449
- if (slideInView) {
4450
- spv += 1;
4451
- }
4221
+ if (slideInView) spv += 1;
4452
4222
  }
4453
4223
  }
4454
4224
  }
@@ -4461,14 +4231,11 @@
4461
4231
  snapGrid,
4462
4232
  params
4463
4233
  } = swiper;
4464
- // Breakpoints
4465
4234
  if (params.breakpoints) {
4466
4235
  swiper.setBreakpoint();
4467
4236
  }
4468
4237
  [...swiper.el.querySelectorAll('[loading="lazy"]')].forEach(imageEl => {
4469
- if (imageEl.complete) {
4470
- processLazyPreloader(swiper, imageEl);
4471
- }
4238
+ if (imageEl.complete) processLazyPreloader(swiper, imageEl);
4472
4239
  });
4473
4240
  swiper.updateSize();
4474
4241
  swiper.updateSlides();
@@ -4482,22 +4249,12 @@
4482
4249
  swiper.updateSlidesClasses();
4483
4250
  }
4484
4251
  let translated;
4485
- if (params.freeMode && params.freeMode.enabled && !params.cssMode) {
4486
- setTranslate();
4487
- if (params.autoHeight) {
4488
- swiper.updateAutoHeight();
4489
- }
4252
+ if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !params.centeredSlides) {
4253
+ translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
4490
4254
  } else {
4491
- if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !params.centeredSlides) {
4492
- const slides = swiper.virtual && params.virtual.enabled ? swiper.virtual.slides : swiper.slides;
4493
- translated = swiper.slideTo(slides.length - 1, 0, false, true);
4494
- } else {
4495
- translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
4496
- }
4497
- if (!translated) {
4498
- setTranslate();
4499
- }
4255
+ translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
4500
4256
  }
4257
+ if (!translated) setTranslate();
4501
4258
  if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
4502
4259
  swiper.checkOverflow();
4503
4260
  }
@@ -4510,7 +4267,6 @@
4510
4267
  const swiper = this;
4511
4268
  const currentDirection = swiper.params.direction;
4512
4269
  if (!newDirection) {
4513
- // eslint-disable-next-line
4514
4270
  newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
4515
4271
  }
4516
4272
  if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {
@@ -4548,15 +4304,11 @@
4548
4304
  mount(element) {
4549
4305
  const swiper = this;
4550
4306
  if (swiper.mounted) return true;
4551
-
4552
- // Find el
4553
4307
  let el = element || swiper.params.el;
4554
4308
  if (typeof el === 'string') {
4555
4309
  el = document.querySelector(el);
4556
4310
  }
4557
- if (!el) {
4558
- return false;
4559
- }
4311
+ if (!el) return false;
4560
4312
  el.swiper = swiper;
4561
4313
  if (el.parentNode && el.parentNode.host && el.parentNode.host.nodeName === swiper.params.swiperElementNodeName.toUpperCase()) {
4562
4314
  swiper.isElement = true;
@@ -4567,12 +4319,10 @@
4567
4319
  const getWrapper = () => {
4568
4320
  if (el && el.shadowRoot && el.shadowRoot.querySelector) {
4569
4321
  const res = el.shadowRoot.querySelector(getWrapperSelector());
4570
- // Children needs to return slot items
4571
4322
  return res;
4572
4323
  }
4573
4324
  return elementChildren(el, getWrapperSelector())[0];
4574
4325
  };
4575
- // Find Wrapper
4576
4326
  let wrapperEl = getWrapper();
4577
4327
  if (!wrapperEl && swiper.params.createElements) {
4578
4328
  wrapperEl = createElement('div', swiper.params.wrapperClass);
@@ -4581,6 +4331,8 @@
4581
4331
  wrapperEl.append(slideEl);
4582
4332
  });
4583
4333
  }
4334
+ const rtl = swiper.params.rtl ?? (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl');
4335
+ const wrongRTL = false;
4584
4336
  Object.assign(swiper, {
4585
4337
  el,
4586
4338
  wrapperEl,
@@ -4588,9 +4340,9 @@
4588
4340
  hostEl: swiper.isElement ? el.parentNode.host : el,
4589
4341
  mounted: true,
4590
4342
  // RTL
4591
- rtl: el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl',
4592
- rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl'),
4593
- wrongRTL: elementStyle(wrapperEl, 'display') === '-webkit-box'
4343
+ rtl,
4344
+ rtlTranslate: swiper.params.direction === 'horizontal' && rtl,
4345
+ wrongRTL
4594
4346
  });
4595
4347
  return true;
4596
4348
  }
@@ -4607,7 +4359,6 @@
4607
4359
  const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
4608
4360
  const swiperTranslate = structuredClone(swiper.snapGrid[1]);
4609
4361
  if (isFirstSlide) {
4610
- // Move last item to first position when at first slide
4611
4362
  const lastSlide = slides.at(-1);
4612
4363
  lastSlide.swiperLoopMoveDOM = true;
4613
4364
  swiper.slidesEl.prepend(lastSlide);
@@ -4619,7 +4370,6 @@
4619
4370
  swiper.setTransition(speed);
4620
4371
  swiper.setTranslate(-swiperTranslate);
4621
4372
  } else if (isLastSlide) {
4622
- // Move first item to last position when at last slide
4623
4373
  const firstSlide = slides[0];
4624
4374
  firstSlide.swiperLoopMoveDOM = true;
4625
4375
  swiper.slidesEl.append(firstSlide);
@@ -4640,42 +4390,24 @@
4640
4390
  const mounted = swiper.mount(el);
4641
4391
  if (mounted === false) return swiper;
4642
4392
  swiper.emit('beforeInit');
4643
-
4644
- // Set breakpoint
4645
4393
  if (swiper.params.breakpoints) {
4646
4394
  swiper.setBreakpoint();
4647
4395
  }
4648
-
4649
- // Add Classes
4650
4396
  swiper.addClasses();
4651
-
4652
- // Update size
4653
4397
  swiper.updateSize();
4654
-
4655
- // Update slides
4656
4398
  swiper.updateSlides();
4657
4399
  if (swiper.params.watchOverflow) {
4658
4400
  swiper.checkOverflow();
4659
4401
  }
4660
-
4661
- // Set Grab Cursor
4662
4402
  if (swiper.params.grabCursor && swiper.enabled) {
4663
4403
  swiper.setGrabCursor();
4664
4404
  }
4665
4405
 
4666
- // Slide To Initial Slide
4667
- if (swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) {
4668
- swiper.slideTo(swiper.params.initialSlide + swiper.virtual.slidesBefore, 0, swiper.params.runCallbacksOnInit, false, true);
4669
- } else {
4670
- swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
4671
- }
4672
-
4673
- // Create loop
4406
+ // Slide to initial slide (core-lite: no optional feature initial offsets)
4407
+ swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
4674
4408
  if (swiper.params.loop) {
4675
4409
  swiper.loopCreate(undefined, true);
4676
4410
  }
4677
-
4678
- // Attach events
4679
4411
  swiper.attachEvents();
4680
4412
  const lazyElements = [...swiper.el.querySelectorAll('[loading="lazy"]')];
4681
4413
  if (swiper.isElement) {
@@ -4685,16 +4417,11 @@
4685
4417
  if (imageEl.complete) {
4686
4418
  processLazyPreloader(swiper, imageEl);
4687
4419
  } else {
4688
- imageEl.addEventListener('load', e => {
4689
- processLazyPreloader(swiper, e.target);
4690
- });
4420
+ imageEl.addEventListener('load', e => processLazyPreloader(swiper, e.target));
4691
4421
  }
4692
4422
  });
4693
4423
  preload(swiper);
4694
-
4695
- // Init Flag
4696
4424
  swiper.initialized = true;
4697
- preload(swiper);
4698
4425
 
4699
4426
  // Emit
4700
4427
  swiper.emit('init');
@@ -4719,27 +4446,15 @@
4719
4446
  return null;
4720
4447
  }
4721
4448
  swiper.emit('beforeDestroy');
4722
-
4723
- // Init Flag
4724
4449
  swiper.initialized = false;
4725
-
4726
- // Detach events
4727
4450
  swiper.detachEvents();
4728
-
4729
- // Destroy loop
4730
4451
  if (params.loop) {
4731
4452
  swiper.loopDestroy();
4732
4453
  }
4733
-
4734
- // Cleanup styles
4735
4454
  if (cleanStyles) {
4736
4455
  swiper.removeClasses();
4737
- if (el && typeof el !== 'string') {
4738
- el.removeAttribute('style');
4739
- }
4740
- if (wrapperEl) {
4741
- wrapperEl.removeAttribute('style');
4742
- }
4456
+ if (el && typeof el !== 'string') el.removeAttribute('style');
4457
+ if (wrapperEl) wrapperEl.removeAttribute('style');
4743
4458
  if (slides && slides.length) {
4744
4459
  slides.forEach(slideEl => {
4745
4460
  slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
@@ -4749,8 +4464,6 @@
4749
4464
  }
4750
4465
  }
4751
4466
  swiper.emit('destroy');
4752
-
4753
- // Detach emitter events
4754
4467
  Object.keys(swiper.eventsListeners).forEach(eventName => {
4755
4468
  swiper.off(eventName);
4756
4469
  });
@@ -5121,7 +4834,7 @@
5121
4834
  }
5122
4835
 
5123
4836
  /**
5124
- * Swiper Custom Element 0.0.15
4837
+ * Swiper Custom Element 0.0.17-dev.1
5125
4838
  * Gem SDK - Swiper, Customized of swiper
5126
4839
  * https://swiperjs.com
5127
4840
  *
@@ -5129,7 +4842,7 @@
5129
4842
  *
5130
4843
  * Released under the MIT License
5131
4844
  *
5132
- * Released on: March 20, 2026
4845
+ * Released on: March 23, 2026
5133
4846
  */
5134
4847
 
5135
4848