@gem-sdk/swiper 0.0.7 → 0.0.9

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.
Files changed (51) hide show
  1. package/modules/a11y.min.mjs +1 -1
  2. package/modules/a11y.mjs +1 -1
  3. package/modules/pagination.min.mjs +1 -1
  4. package/modules/pagination.min.mjs.map +1 -1
  5. package/modules/pagination.mjs +20 -16
  6. package/package.json +3 -3
  7. package/shared/swiper-core.min.mjs +1 -1
  8. package/shared/swiper-core.min.mjs.map +1 -1
  9. package/shared/swiper-core.mjs +425 -52
  10. package/shared/update-swiper.min.mjs +1 -1
  11. package/shared/update-swiper.min.mjs.map +1 -1
  12. package/shared/update-swiper.mjs +1 -1
  13. package/shared/utils.min.mjs +1 -1
  14. package/shared/utils.min.mjs.map +1 -1
  15. package/shared/utils.mjs +1 -1
  16. package/swiper-bundle.css +2 -2
  17. package/swiper-bundle.js +448 -71
  18. package/swiper-bundle.min.css +2 -2
  19. package/swiper-bundle.min.js +3 -3
  20. package/swiper-bundle.min.js.map +1 -1
  21. package/swiper-bundle.min.mjs +2 -2
  22. package/swiper-bundle.mjs +2 -2
  23. package/swiper-effect-utils.min.mjs +2 -2
  24. package/swiper-effect-utils.mjs +2 -2
  25. package/swiper-element-bundle.js +451 -74
  26. package/swiper-element-bundle.min.js +3 -3
  27. package/swiper-element-bundle.min.js.map +1 -1
  28. package/swiper-element-bundle.min.mjs +2 -2
  29. package/swiper-element-bundle.mjs +2 -2
  30. package/swiper-element.d.ts +5 -0
  31. package/swiper-element.js +429 -56
  32. package/swiper-element.min.js +3 -3
  33. package/swiper-element.min.js.map +1 -1
  34. package/swiper-element.min.mjs +2 -2
  35. package/swiper-element.mjs +2 -2
  36. package/swiper-react.d.ts +5 -0
  37. package/swiper-react.mjs +2 -2
  38. package/swiper-vue.d.ts +9 -0
  39. package/swiper-vue.mjs +7 -3
  40. package/swiper.css +2 -2
  41. package/swiper.js +426 -53
  42. package/swiper.less +2 -2
  43. package/swiper.min.css +2 -2
  44. package/swiper.min.js +3 -3
  45. package/swiper.min.js.map +1 -1
  46. package/swiper.min.mjs +2 -2
  47. package/swiper.mjs +2 -2
  48. package/swiper.scss +2 -2
  49. package/types/swiper-class.d.ts +10 -0
  50. package/types/swiper-events.d.ts +5 -0
  51. package/types/swiper-options.d.ts +7 -0
package/swiper-element.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Swiper Custom Element 0.0.7
2
+ * Swiper Custom Element 0.0.9
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: October 9, 2025
10
+ * Released on: December 8, 2025
11
11
  */
12
12
 
13
13
  (function () {
@@ -2000,56 +2000,63 @@
2000
2000
  if (typeof speed === 'undefined') {
2001
2001
  speed = swiper.params.speed;
2002
2002
  }
2003
- const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
2004
2003
  let newIndex = index;
2005
2004
  if (swiper.params.loop) {
2006
- if (swiper.virtual && swiper.params.virtual.enabled) {
2007
- // eslint-disable-next-line
2008
- newIndex = newIndex + swiper.virtual.slidesBefore;
2005
+ swiper.slides;
2006
+ const totalSlides = swiper.slides.length;
2007
+ let targetSlideIndex;
2008
+ targetSlideIndex = swiper.getSlideIndexByData(newIndex);
2009
+ const cols = swiper.slides.length;
2010
+ const {
2011
+ centeredSlides
2012
+ } = swiper.params;
2013
+ let slidesPerView = swiper.params.slidesPerView;
2014
+ if (slidesPerView === 'auto') {
2015
+ slidesPerView = swiper.slidesPerViewDynamic();
2009
2016
  } else {
2010
- let targetSlideIndex;
2011
- if (gridEnabled) {
2012
- const slideIndex = newIndex * swiper.params.grid.rows;
2013
- targetSlideIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column;
2014
- } else {
2015
- targetSlideIndex = swiper.getSlideIndexByData(newIndex);
2016
- }
2017
- const cols = gridEnabled ? Math.ceil(swiper.slides.length / swiper.params.grid.rows) : swiper.slides.length;
2018
- const {
2019
- centeredSlides
2020
- } = swiper.params;
2021
- let slidesPerView = swiper.params.slidesPerView;
2022
- if (slidesPerView === 'auto') {
2023
- slidesPerView = swiper.slidesPerViewDynamic();
2024
- } else {
2025
- slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2026
- if (centeredSlides && slidesPerView % 2 === 0) {
2027
- slidesPerView = slidesPerView + 1;
2028
- }
2029
- }
2030
- let needLoopFix = cols - targetSlideIndex < slidesPerView;
2031
- if (centeredSlides) {
2032
- needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
2033
- }
2034
- if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
2035
- needLoopFix = false;
2036
- }
2037
- if (needLoopFix) {
2038
- const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
2039
- swiper.loopFix({
2040
- direction,
2041
- slideTo: true,
2042
- activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2043
- slideRealIndex: direction === 'next' ? swiper.realIndex : undefined
2044
- });
2017
+ slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2018
+ if (centeredSlides && slidesPerView % 2 === 0) {
2019
+ slidesPerView = slidesPerView + 1;
2045
2020
  }
2046
- if (gridEnabled) {
2047
- const slideIndex = newIndex * swiper.params.grid.rows;
2048
- newIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column;
2021
+ }
2022
+ let needLoopFix = cols - targetSlideIndex < slidesPerView;
2023
+ if (centeredSlides) {
2024
+ needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
2025
+ }
2026
+ if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto') {
2027
+ needLoopFix = false;
2028
+ }
2029
+ if (centeredSlides && needLoopFix) {
2030
+ const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
2031
+ swiper.loopFix({
2032
+ direction,
2033
+ slideTo: true,
2034
+ activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2035
+ slideRealIndex: direction === 'next' ? swiper.realIndex : undefined
2036
+ });
2037
+ }
2038
+ if (!centeredSlides && needLoopFix) {
2039
+ let direction;
2040
+ let nextSteps;
2041
+ let prevSteps;
2042
+ if (swiper.activeIndex < targetSlideIndex) {
2043
+ nextSteps = targetSlideIndex - swiper.activeIndex;
2044
+ prevSteps = swiper.activeIndex - (targetSlideIndex - totalSlides);
2049
2045
  } else {
2050
- newIndex = swiper.getSlideIndexByData(newIndex);
2046
+ prevSteps = swiper.activeIndex - targetSlideIndex;
2047
+ nextSteps = targetSlideIndex + totalSlides - swiper.activeIndex;
2051
2048
  }
2049
+ direction = nextSteps > prevSteps ? 'prev' : 'next';
2050
+ swiper.loopFixDot({
2051
+ direction,
2052
+ slideTo: true,
2053
+ activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2054
+ slideRealIndex: direction === 'next' ? swiper.realIndex : undefined,
2055
+ targetSlideIndex,
2056
+ newIndex: swiper.getSlideIndexByData(newIndex)
2057
+ });
2052
2058
  }
2059
+ newIndex = swiper.getSlideIndexByData(newIndex);
2053
2060
  }
2054
2061
  requestAnimationFrame(() => {
2055
2062
  swiper.slideTo(newIndex, speed, runCallbacks, internal);
@@ -2057,6 +2064,87 @@
2057
2064
  return swiper;
2058
2065
  }
2059
2066
 
2067
+ function slideToLoopCenterSneakPeek(index, speed, runCallbacks, internal) {
2068
+ if (index === void 0) {
2069
+ index = 0;
2070
+ }
2071
+ if (runCallbacks === void 0) {
2072
+ runCallbacks = true;
2073
+ }
2074
+ if (typeof index === 'string') {
2075
+ const indexAsNumber = parseInt(index, 10);
2076
+ index = indexAsNumber;
2077
+ }
2078
+ const swiper = this;
2079
+ if (swiper.destroyed) return;
2080
+ if (typeof speed === 'undefined') {
2081
+ speed = swiper.params.speed;
2082
+ }
2083
+ let newIndex = index;
2084
+ if (swiper.params.loop) {
2085
+ swiper.slides;
2086
+ const totalSlides = swiper.slides.length;
2087
+ let targetSlideIndex;
2088
+ targetSlideIndex = swiper.getSlideIndexByData(newIndex);
2089
+ const cols = swiper.slides.length;
2090
+ const {
2091
+ centeredSlides
2092
+ } = swiper.params;
2093
+ let slidesPerView = swiper.params.slidesPerView;
2094
+ if (slidesPerView === 'auto') {
2095
+ slidesPerView = swiper.slidesPerViewDynamic();
2096
+ } else {
2097
+ slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2098
+ if (centeredSlides && slidesPerView % 2 === 0) {
2099
+ slidesPerView = slidesPerView + 1;
2100
+ }
2101
+ }
2102
+ if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto') ;
2103
+ const isSneakPeekCenter = swiper.params?.isSneakPeekCenter;
2104
+ if (isSneakPeekCenter) {
2105
+ let direction;
2106
+ let nextSteps;
2107
+ let prevSteps;
2108
+ if (swiper.activeIndex < targetSlideIndex) {
2109
+ nextSteps = targetSlideIndex - swiper.activeIndex;
2110
+ prevSteps = swiper.activeIndex - (targetSlideIndex - totalSlides);
2111
+ } else {
2112
+ prevSteps = swiper.activeIndex - targetSlideIndex;
2113
+ nextSteps = targetSlideIndex + totalSlides - swiper.activeIndex;
2114
+ }
2115
+ direction = nextSteps > prevSteps ? 'prev' : 'next';
2116
+ swiper.loopFixDot({
2117
+ direction,
2118
+ slideTo: true,
2119
+ activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2120
+ slideRealIndex: direction === 'next' ? swiper.realIndex : undefined,
2121
+ targetSlideIndex,
2122
+ newIndex: swiper.getSlideIndexByData(newIndex)
2123
+ });
2124
+ }
2125
+ newIndex = swiper.getSlideIndexByData(newIndex);
2126
+ }
2127
+ swiper.slideTo(newIndex, speed, runCallbacks, internal);
2128
+ const slides = swiper.slides;
2129
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
2130
+ const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
2131
+ 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
+ const lastSlide = slides[slides.length - 1];
2135
+ lastSlide.swiperLoopMoveDOM = true;
2136
+ swiper.slidesEl.prepend(lastSlide);
2137
+ lastSlide.swiperLoopMoveDOM = false;
2138
+ swiper.setTransition(0);
2139
+ swiper.setTranslate(-(swiperTranslate + gap));
2140
+ swiper.recalcSlides();
2141
+ swiper.updateSlides();
2142
+ swiper.setTransition(swiper.params.speed);
2143
+ swiper.setTranslate(-swiperTranslate);
2144
+ }
2145
+ return;
2146
+ }
2147
+
2060
2148
  /* eslint no-unused-vars: "off" */
2061
2149
  function slideNext(speed, runCallbacks, internal) {
2062
2150
  if (runCallbacks === void 0) {
@@ -2081,7 +2169,7 @@
2081
2169
  if (params.loop) {
2082
2170
  if (animating && !isVirtual && params.loopPreventsSliding) return false;
2083
2171
 
2084
- // Check if loop is disabled
2172
+ // Kiểm tra xem loop bị disable không
2085
2173
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
2086
2174
  if (swiper.slides.length >= currentSlidesPerView) {
2087
2175
  swiper.loopFix({
@@ -2100,7 +2188,27 @@
2100
2188
  if (params.rewind && swiper.isEnd) {
2101
2189
  return swiper.slideTo(0, speed, runCallbacks, internal);
2102
2190
  }
2103
- return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
2191
+ requestAnimationFrame(() => {
2192
+ swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
2193
+ const slides = swiper.slides;
2194
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1 && (swiper.activeIndex === slides.length - 1 || swiper.isEnd)) {
2195
+ const lastSnapGridIndex = swiper.snapGrid.length - 1;
2196
+ const gap = Math.abs(swiper.snapGrid[lastSnapGridIndex] - swiper.snapGrid[lastSnapGridIndex - 1]);
2197
+ const swiperTranslate = structuredClone(swiper.snapGrid[lastSnapGridIndex - 1]);
2198
+
2199
+ // Move first item to last position only if active slide is the last slide
2200
+ const firstSlide = slides[0];
2201
+ firstSlide.swiperLoopMoveDOM = true;
2202
+ swiper.slidesEl.append(firstSlide);
2203
+ firstSlide.swiperLoopMoveDOM = false;
2204
+ swiper.setTransition(0);
2205
+ swiper.setTranslate(-(swiperTranslate - gap));
2206
+ swiper.recalcSlides();
2207
+ swiper.updateSlides();
2208
+ swiper.setTransition(swiper.params.speed);
2209
+ swiper.setTranslate(-swiperTranslate);
2210
+ }
2211
+ });
2104
2212
  }
2105
2213
 
2106
2214
  /* eslint no-unused-vars: "off" */
@@ -2121,11 +2229,9 @@
2121
2229
  if (typeof speed === 'undefined') {
2122
2230
  speed = swiper.params.speed;
2123
2231
  }
2124
- const isVirtual = swiper.virtual && params.virtual.enabled;
2232
+ swiper.virtual && params.virtual.enabled;
2125
2233
  if (params.loop) {
2126
- if (animating && !isVirtual && params.loopPreventsSliding) return false;
2127
-
2128
- // Check if loop is disabled
2234
+ // Kiểm tra xem loop bị disable không
2129
2235
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
2130
2236
  if (swiper.slides.length >= currentSlidesPerView) {
2131
2237
  swiper.loopFix({
@@ -2174,7 +2280,27 @@
2174
2280
  });
2175
2281
  return true;
2176
2282
  }
2177
- return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
2283
+ requestAnimationFrame(() => {
2284
+ swiper.slideTo(prevIndex, speed, runCallbacks, internal);
2285
+ const slides = swiper.slides;
2286
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
2287
+ const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
2288
+ 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
+ const lastSlide = slides[slides.length - 1];
2292
+ lastSlide.swiperLoopMoveDOM = true;
2293
+ swiper.slidesEl.prepend(lastSlide);
2294
+ lastSlide.swiperLoopMoveDOM = false;
2295
+ swiper.setTransition(0);
2296
+ swiper.setTranslate(-(swiperTranslate + gap));
2297
+ swiper.recalcSlides();
2298
+ swiper.updateSlides();
2299
+ swiper.setTransition(swiper.params.speed);
2300
+ swiper.setTranslate(-swiperTranslate);
2301
+ }
2302
+ });
2303
+ return;
2178
2304
  }
2179
2305
 
2180
2306
  /* eslint no-unused-vars: "off" */
@@ -2263,6 +2389,7 @@
2263
2389
  var slide = {
2264
2390
  slideTo,
2265
2391
  slideToLoop,
2392
+ slideToLoopCenterSneakPeek,
2266
2393
  slideNext,
2267
2394
  slidePrev,
2268
2395
  slideReset,
@@ -2350,7 +2477,7 @@
2350
2477
  const swiper = this;
2351
2478
  if (!swiper.params.loop) return;
2352
2479
 
2353
- // Disable loop mode if the number of slides is less than slidesPerView
2480
+ // Disable loop mode nếu số slides ít hơn slidesPerView
2354
2481
  const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2355
2482
  if (swiper.slides.length < currentSlidesPerView) {
2356
2483
  console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
@@ -2562,6 +2689,206 @@
2562
2689
  swiper.emit('loopFix');
2563
2690
  }
2564
2691
 
2692
+ function loopFixDot(_temp) {
2693
+ let {
2694
+ slideRealIndex,
2695
+ slideTo = true,
2696
+ direction,
2697
+ activeSlideIndex,
2698
+ initial,
2699
+ targetSlideIndex,
2700
+ newIndex
2701
+ } = _temp === void 0 ? {} : _temp;
2702
+ const swiper = this;
2703
+ if (!swiper.params.loop) return;
2704
+
2705
+ // Disable loop mode nếu số slides ít hơn slidesPerView
2706
+ const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2707
+ if (swiper.slides.length < currentSlidesPerView) {
2708
+ console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
2709
+ return;
2710
+ }
2711
+ swiper.emit('beforeLoopFix');
2712
+ const {
2713
+ slides,
2714
+ allowSlidePrev,
2715
+ allowSlideNext,
2716
+ slidesEl,
2717
+ params
2718
+ } = swiper;
2719
+ const targetData = slidesEl.children[targetSlideIndex].getAttribute('data-swiper-slide-index');
2720
+ const oldActiveData = Array.from(slidesEl.children).find(el => el.classList.contains(params.slideActiveClass)).getAttribute('data-swiper-slide-index');
2721
+ const {
2722
+ centeredSlides,
2723
+ initialSlide
2724
+ } = params;
2725
+ const swiperDataOldActiveIndex = slidesEl.children[swiper.activeIndex].getAttribute('data-swiper-slide-index');
2726
+ swiper.allowSlidePrev = true;
2727
+ swiper.allowSlideNext = true;
2728
+ let slidesPerView = params.slidesPerView;
2729
+ if (slidesPerView === 'auto') {
2730
+ slidesPerView = swiper.slidesPerViewDynamic();
2731
+ } else {
2732
+ slidesPerView = Math.ceil(parseFloat(params.slidesPerView, 10));
2733
+ if (centeredSlides && slidesPerView % 2 === 0) {
2734
+ slidesPerView = slidesPerView + 1;
2735
+ }
2736
+ }
2737
+ const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup;
2738
+ let loopedSlides = centeredSlides ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) : slidesPerGroup;
2739
+ if (loopedSlides % slidesPerGroup !== 0) {
2740
+ loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup;
2741
+ }
2742
+ loopedSlides += params.loopAdditionalSlides;
2743
+ swiper.loopedSlides = loopedSlides;
2744
+ if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2745
+ 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');
2746
+ }
2747
+ const isNext = direction === 'next' || !direction;
2748
+ const isPrev = direction === 'prev' || !direction;
2749
+ let numberOfSlidesNeedClone = [];
2750
+ let slidesIndex = [];
2751
+ for (let i = 0; i < slidesEl.children.length; i++) {
2752
+ slidesIndex.push(slidesEl.children[i].getAttribute('data-swiper-slide-index'));
2753
+ }
2754
+ if (isPrev) {
2755
+ for (let i = targetSlideIndex; i < slidesEl.children.length; i++) {
2756
+ numberOfSlidesNeedClone.push(i);
2757
+ }
2758
+ } else if (isNext) {
2759
+ for (let i = 0; i < slidesPerView - (slidesEl.children.length - targetSlideIndex); i++) {
2760
+ numberOfSlidesNeedClone.push(i);
2761
+ }
2762
+ }
2763
+ const cols = slides.length;
2764
+ const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !centeredSlides;
2765
+ isInitialOverflow ? initialSlide : swiper.activeIndex;
2766
+ if (typeof activeSlideIndex === 'undefined') {
2767
+ activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass)));
2768
+ }
2769
+
2770
+ // Tạo DocumentFragment để chứa các slide clone
2771
+ const cloneFragment = document.createDocumentFragment();
2772
+
2773
+ // Clone các slide theo numberOfSlidesNeedClone (đã đảo ngược) và thêm vào fragment
2774
+ (isNext ? numberOfSlidesNeedClone : numberOfSlidesNeedClone.reverse()).forEach(index => {
2775
+ if (slides[index]) {
2776
+ const originalSlide = slides[index];
2777
+ const clonedSlide = originalSlide.cloneNode(true);
2778
+
2779
+ // Đánh dấu slide clone
2780
+ clonedSlide.setAttribute('data-swiper-clone', 'true');
2781
+ clonedSlide.classList.add('swiper-slide-clone');
2782
+
2783
+ // Thêm clone vào fragment
2784
+ cloneFragment.appendChild(clonedSlide);
2785
+ }
2786
+ });
2787
+ if (isPrev) {
2788
+ numberOfSlidesNeedClone.forEach(index => {
2789
+ const originalSlide = slides[index];
2790
+ originalSlide.swiperLoopMoveDOM = true;
2791
+ slidesEl.prepend(originalSlide);
2792
+ originalSlide.swiperLoopMoveDOM = false;
2793
+ });
2794
+ }
2795
+ if (isNext) {
2796
+ numberOfSlidesNeedClone.forEach(index => {
2797
+ const originalSlide = slides[index];
2798
+ originalSlide.swiperLoopMoveDOM = true;
2799
+ slidesEl.append(originalSlide);
2800
+ originalSlide.swiperLoopMoveDOM = false;
2801
+ });
2802
+ }
2803
+
2804
+ // Sắp xếp cloneFragment theo data-swiper-slide-index tăng dần
2805
+ const clonedSlides = Array.from(cloneFragment.children);
2806
+ clonedSlides.sort((a, b) => {
2807
+ const indexA = parseInt(a.getAttribute('data-swiper-slide-index')) || 0;
2808
+ const indexB = parseInt(b.getAttribute('data-swiper-slide-index')) || 0;
2809
+ return indexA - indexB;
2810
+ });
2811
+
2812
+ // Xóa tất cả children cũ và thêm lại theo thứ tự đã sắp xếp
2813
+ cloneFragment.innerHTML = '';
2814
+ clonedSlides.forEach(slide => {
2815
+ cloneFragment.appendChild(slide);
2816
+ });
2817
+
2818
+ // Thêm fragment vào vị trí phù hợp
2819
+ if (isPrev) {
2820
+ // Nếu là prev, thêm fragment vào cuối slidesEl
2821
+ slidesEl.appendChild(cloneFragment);
2822
+ } else if (isNext) {
2823
+ // Nếu là next, thêm fragment vào đầu slidesEl
2824
+ slidesEl.insertBefore(cloneFragment, slidesEl.firstChild);
2825
+ }
2826
+ swiper.recalcSlides();
2827
+ swiper.updateSlides();
2828
+
2829
+ // Tìm slide có data-swiper-slide-index tương ứng
2830
+ let oldActiveIndex = null;
2831
+ for (let i = 0; i < slidesEl.children.length; i++) {
2832
+ const child = slidesEl.children[i];
2833
+ if (child.getAttribute('data-swiper-slide-index') === swiperDataOldActiveIndex) {
2834
+ oldActiveIndex = i;
2835
+ break;
2836
+ }
2837
+ }
2838
+ if (slideTo && oldActiveIndex !== swiper.activeIndex) {
2839
+ swiper.slideTo(oldActiveIndex, 0);
2840
+ }
2841
+
2842
+ // Tìm vị trí slide cũ sau khi remove clone để set lại translate tạo hiệu ứng animate
2843
+ const skip = Math.min(swiper.params.slidesPerGroupSkip, newIndex);
2844
+ let snapIndex = skip + Math.floor((newIndex - skip) / swiper.params.slidesPerGroup);
2845
+ if (snapIndex >= swiper.snapGrid.length) snapIndex = swiper.snapGrid.length - 1;
2846
+ const translate = -swiper.snapGrid[snapIndex];
2847
+ if (translate === swiper.translate) {
2848
+ let oldActiveIndexAfterRemoveClone;
2849
+ for (let i = 0; i < slidesEl.children.length; i++) {
2850
+ const child = slidesEl.children[i];
2851
+ if (child.getAttribute('data-swiper-slide-index') === swiperDataOldActiveIndex) {
2852
+ oldActiveIndexAfterRemoveClone = i;
2853
+ break;
2854
+ }
2855
+ }
2856
+ const skip = Math.min(swiper.params.slidesPerGroupSkip, oldActiveIndexAfterRemoveClone);
2857
+ let snapIndex = skip + Math.floor((oldActiveIndexAfterRemoveClone - skip) / swiper.params.slidesPerGroup);
2858
+ if (snapIndex >= swiper.snapGrid.length) snapIndex = swiper.snapGrid.length - 1;
2859
+ const oldTranslate = -swiper.snapGrid[snapIndex];
2860
+ let updateTranslate;
2861
+ if (oldTranslate === swiper.translate) {
2862
+ updateTranslate = swiper.snapGrid[snapIndex > 0 ? snapIndex - 1 : swiper.snapGrid.length - 1];
2863
+ } else {
2864
+ updateTranslate = oldTranslate;
2865
+ }
2866
+ swiper.setTranslate(updateTranslate);
2867
+ }
2868
+ // Remove slide clone ra khỏi slidesEl sau khi slideTo hoàn thành
2869
+ const cloneSlides = slidesEl.querySelectorAll('[data-swiper-clone="true"]');
2870
+ cloneSlides.forEach(cloneSlide => {
2871
+ if (cloneSlide.parentNode) {
2872
+ cloneSlide.parentNode.removeChild(cloneSlide);
2873
+ }
2874
+ });
2875
+ swiper.recalcSlides();
2876
+ swiper.updateSlides();
2877
+ const targetDataIndex = Array.from(slidesEl.children).findIndex(el => el.getAttribute('data-swiper-slide-index') * 1 === targetData * 1);
2878
+ const oldDataIndex = Array.from(slidesEl.children).findIndex(el => el.getAttribute('data-swiper-slide-index') * 1 === oldActiveData * 1);
2879
+ const snapIndexNew = skip + Math.floor((targetDataIndex - skip) / swiper.params.slidesPerGroup);
2880
+ const snapIndexOld = skip + Math.floor((oldDataIndex - skip) / swiper.params.slidesPerGroup);
2881
+ if (slideTo && snapIndexNew === targetDataIndex) {
2882
+ const translateOld = -swiper.snapGrid[snapIndexOld > swiper.snapGrid.length - 1 ? snapIndexNew - 1 > swiper.snapGrid.length - 1 ? 0 : snapIndexNew - 1 : snapIndexOld];
2883
+ swiper.setTranslate(translateOld);
2884
+ }
2885
+ swiper.recalcSlides();
2886
+ swiper.updateSlides();
2887
+ swiper.allowSlidePrev = allowSlidePrev;
2888
+ swiper.allowSlideNext = allowSlideNext;
2889
+ swiper.emit('loopFixDot');
2890
+ }
2891
+
2565
2892
  function loopDestroy() {
2566
2893
  const swiper = this;
2567
2894
  const {
@@ -2588,6 +2915,7 @@
2588
2915
  var loop = {
2589
2916
  loopCreate,
2590
2917
  loopFix,
2918
+ loopFixDot,
2591
2919
  loopDestroy
2592
2920
  };
2593
2921
 
@@ -3182,6 +3510,9 @@
3182
3510
  swiper.slideTo(stopIndex);
3183
3511
  }
3184
3512
  }
3513
+ swiper.syncSneakPeekCenter({
3514
+ speed: swiper.params.speed
3515
+ });
3185
3516
  }
3186
3517
 
3187
3518
  function onResize() {
@@ -3723,6 +4054,7 @@
3723
4054
  loopAddBlankSlides: true,
3724
4055
  loopAdditionalSlides: 0,
3725
4056
  loopPreventsSliding: true,
4057
+ isSneakPeekCenter: false,
3726
4058
  // rewind
3727
4059
  rewind: false,
3728
4060
  // Swiping/no swiping
@@ -4264,6 +4596,46 @@
4264
4596
  });
4265
4597
  return true;
4266
4598
  }
4599
+ syncSneakPeekCenter(_temp) {
4600
+ let {
4601
+ speed = 0
4602
+ } = _temp === void 0 ? {} : _temp;
4603
+ const swiper = this;
4604
+ requestAnimationFrame(() => {
4605
+ const slides = swiper.slides;
4606
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1) {
4607
+ const isFirstSlide = swiper.activeIndex === 0;
4608
+ const isLastSlide = swiper.activeIndex === slides.length - 1 || swiper.isEnd;
4609
+ const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
4610
+ const swiperTranslate = structuredClone(swiper.snapGrid[1]);
4611
+ if (isFirstSlide) {
4612
+ // Move last item to first position when at first slide
4613
+ const lastSlide = slides.at(-1);
4614
+ lastSlide.swiperLoopMoveDOM = true;
4615
+ swiper.slidesEl.prepend(lastSlide);
4616
+ lastSlide.swiperLoopMoveDOM = false;
4617
+ swiper.setTransition(0);
4618
+ swiper.setTranslate(-(swiperTranslate + gap));
4619
+ swiper.recalcSlides();
4620
+ swiper.updateSlides();
4621
+ swiper.setTransition(speed);
4622
+ swiper.setTranslate(-swiperTranslate);
4623
+ } else if (isLastSlide) {
4624
+ // Move first item to last position when at last slide
4625
+ const firstSlide = slides[0];
4626
+ firstSlide.swiperLoopMoveDOM = true;
4627
+ swiper.slidesEl.append(firstSlide);
4628
+ firstSlide.swiperLoopMoveDOM = false;
4629
+ swiper.setTransition(0);
4630
+ swiper.setTranslate(-(swiperTranslate - gap));
4631
+ swiper.recalcSlides();
4632
+ swiper.updateSlides();
4633
+ swiper.setTransition(speed);
4634
+ swiper.setTranslate(-swiperTranslate);
4635
+ }
4636
+ }
4637
+ });
4638
+ }
4267
4639
  init(el) {
4268
4640
  const swiper = this;
4269
4641
  if (swiper.initialized) return swiper;
@@ -4325,6 +4697,7 @@
4325
4697
  // Init Flag
4326
4698
  swiper.initialized = true;
4327
4699
  preload(swiper);
4700
+ swiper.syncSneakPeekCenter();
4328
4701
 
4329
4702
  // Emit
4330
4703
  swiper.emit('init');
@@ -4426,7 +4799,7 @@
4426
4799
  Swiper.use([Resize, Observer]);
4427
4800
 
4428
4801
  /* underscore in name -> watch for changes */
4429
- const paramsList = ['eventsPrefix', 'injectStyles', 'injectStylesUrls', 'modules', 'init', '_direction', 'oneWayMovement', 'swiperElementNodeName', 'touchEventsTarget', 'initialSlide', '_speed', 'cssMode', 'updateOnWindowResize', 'resizeObserver', 'nested', 'focusableElements', '_enabled', '_width', '_height', 'preventInteractionOnTransition', 'userAgent', 'url', '_edgeSwipeDetection', '_edgeSwipeThreshold', '_freeMode', '_autoHeight', 'setWrapperSize', 'virtualTranslate', '_effect', 'breakpoints', 'breakpointsBase', '_spaceBetween', '_slidesPerView', 'maxBackfaceHiddenSlides', '_grid', '_slidesPerGroup', '_slidesPerGroupSkip', '_slidesPerGroupAuto', '_centeredSlides', '_centeredSlidesBounds', '_slidesOffsetBefore', '_slidesOffsetAfter', 'normalizeSlideIndex', '_centerInsufficientSlides', '_watchOverflow', 'roundLengths', 'touchRatio', 'touchAngle', 'simulateTouch', '_shortSwipes', '_longSwipes', 'longSwipesRatio', 'longSwipesMs', '_followFinger', 'allowTouchMove', '_threshold', 'touchMoveStopPropagation', 'touchStartPreventDefault', 'touchStartForcePreventDefault', 'touchReleaseOnEdges', 'uniqueNavElements', '_resistance', '_resistanceRatio', '_watchSlidesProgress', '_grabCursor', 'preventClicks', 'preventClicksPropagation', '_slideToClickedSlide', '_loop', 'loopAdditionalSlides', 'loopAddBlankSlides', 'loopPreventsSliding', '_rewind', '_allowSlidePrev', '_allowSlideNext', '_swipeHandler', '_noSwiping', 'noSwipingClass', 'noSwipingSelector', 'passiveListeners', 'containerModifierClass', 'slideClass', 'slideActiveClass', 'slideVisibleClass', 'slideFullyVisibleClass', 'slideNextClass', 'slidePrevClass', 'slideBlankClass', 'wrapperClass', 'lazyPreloaderClass', 'lazyPreloadPrevNext', 'runCallbacksOnInit', 'observer', 'observeParents', 'observeSlideChildren',
4802
+ const paramsList = ['eventsPrefix', 'injectStyles', 'injectStylesUrls', 'modules', 'init', '_direction', 'oneWayMovement', 'swiperElementNodeName', 'touchEventsTarget', 'initialSlide', '_speed', 'cssMode', 'updateOnWindowResize', 'resizeObserver', 'nested', 'focusableElements', '_enabled', '_width', '_height', 'preventInteractionOnTransition', 'userAgent', 'url', '_edgeSwipeDetection', '_edgeSwipeThreshold', '_freeMode', '_autoHeight', 'setWrapperSize', 'virtualTranslate', '_effect', 'breakpoints', 'breakpointsBase', '_spaceBetween', '_isSneakPeekCenter', '_slidesPerView', 'maxBackfaceHiddenSlides', '_grid', '_slidesPerGroup', '_slidesPerGroupSkip', '_slidesPerGroupAuto', '_centeredSlides', '_centeredSlidesBounds', '_slidesOffsetBefore', '_slidesOffsetAfter', 'normalizeSlideIndex', '_centerInsufficientSlides', '_watchOverflow', 'roundLengths', 'touchRatio', 'touchAngle', 'simulateTouch', '_shortSwipes', '_longSwipes', 'longSwipesRatio', 'longSwipesMs', '_followFinger', 'allowTouchMove', '_threshold', 'touchMoveStopPropagation', 'touchStartPreventDefault', 'touchStartForcePreventDefault', 'touchReleaseOnEdges', 'uniqueNavElements', '_resistance', '_resistanceRatio', '_watchSlidesProgress', '_grabCursor', 'preventClicks', 'preventClicksPropagation', '_slideToClickedSlide', '_loop', 'loopAdditionalSlides', 'loopAddBlankSlides', 'loopPreventsSliding', '_rewind', '_allowSlidePrev', '_allowSlideNext', '_swipeHandler', '_noSwiping', 'noSwipingClass', 'noSwipingSelector', 'passiveListeners', 'containerModifierClass', 'slideClass', 'slideActiveClass', 'slideVisibleClass', 'slideFullyVisibleClass', 'slideNextClass', 'slidePrevClass', 'slideBlankClass', 'wrapperClass', 'lazyPreloaderClass', 'lazyPreloadPrevNext', 'runCallbacksOnInit', 'observer', 'observeParents', 'observeSlideChildren',
4430
4803
  // modules
4431
4804
  'a11y', '_autoplay', '_controller', 'coverflowEffect', 'cubeEffect', 'fadeEffect', 'flipEffect', 'creativeEffect', 'cardsEffect', 'hashNavigation', 'history', 'keyboard', 'mousewheel', '_navigation', '_pagination', 'parallax', '_scrollbar', '_thumbs', 'virtual', 'zoom', 'control'];
4432
4805
 
@@ -4751,7 +5124,7 @@
4751
5124
  }
4752
5125
 
4753
5126
  /**
4754
- * Swiper Custom Element 0.0.7
5127
+ * Swiper Custom Element 0.0.9
4755
5128
  * Gem SDK - Swiper, Customized of swiper
4756
5129
  * https://swiperjs.com
4757
5130
  *
@@ -4759,7 +5132,7 @@
4759
5132
  *
4760
5133
  * Released under the MIT License
4761
5134
  *
4762
- * Released on: October 9, 2025
5135
+ * Released on: December 8, 2025
4763
5136
  */
4764
5137
 
4765
5138