@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Swiper 0.0.7
2
+ * Swiper 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
  var Swiper = (function () {
@@ -1988,56 +1988,63 @@ var Swiper = (function () {
1988
1988
  if (typeof speed === 'undefined') {
1989
1989
  speed = swiper.params.speed;
1990
1990
  }
1991
- const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
1992
1991
  let newIndex = index;
1993
1992
  if (swiper.params.loop) {
1994
- if (swiper.virtual && swiper.params.virtual.enabled) {
1995
- // eslint-disable-next-line
1996
- newIndex = newIndex + swiper.virtual.slidesBefore;
1993
+ swiper.slides;
1994
+ const totalSlides = swiper.slides.length;
1995
+ let targetSlideIndex;
1996
+ targetSlideIndex = swiper.getSlideIndexByData(newIndex);
1997
+ const cols = swiper.slides.length;
1998
+ const {
1999
+ centeredSlides
2000
+ } = swiper.params;
2001
+ let slidesPerView = swiper.params.slidesPerView;
2002
+ if (slidesPerView === 'auto') {
2003
+ slidesPerView = swiper.slidesPerViewDynamic();
1997
2004
  } else {
1998
- let targetSlideIndex;
1999
- if (gridEnabled) {
2000
- const slideIndex = newIndex * swiper.params.grid.rows;
2001
- targetSlideIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column;
2002
- } else {
2003
- targetSlideIndex = swiper.getSlideIndexByData(newIndex);
2004
- }
2005
- const cols = gridEnabled ? Math.ceil(swiper.slides.length / swiper.params.grid.rows) : swiper.slides.length;
2006
- const {
2007
- centeredSlides
2008
- } = swiper.params;
2009
- let slidesPerView = swiper.params.slidesPerView;
2010
- if (slidesPerView === 'auto') {
2011
- slidesPerView = swiper.slidesPerViewDynamic();
2012
- } else {
2013
- slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2014
- if (centeredSlides && slidesPerView % 2 === 0) {
2015
- slidesPerView = slidesPerView + 1;
2016
- }
2017
- }
2018
- let needLoopFix = cols - targetSlideIndex < slidesPerView;
2019
- if (centeredSlides) {
2020
- needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
2021
- }
2022
- if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
2023
- needLoopFix = false;
2024
- }
2025
- if (needLoopFix) {
2026
- const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
2027
- swiper.loopFix({
2028
- direction,
2029
- slideTo: true,
2030
- activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2031
- slideRealIndex: direction === 'next' ? swiper.realIndex : undefined
2032
- });
2005
+ slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2006
+ if (centeredSlides && slidesPerView % 2 === 0) {
2007
+ slidesPerView = slidesPerView + 1;
2033
2008
  }
2034
- if (gridEnabled) {
2035
- const slideIndex = newIndex * swiper.params.grid.rows;
2036
- newIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column;
2009
+ }
2010
+ let needLoopFix = cols - targetSlideIndex < slidesPerView;
2011
+ if (centeredSlides) {
2012
+ needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
2013
+ }
2014
+ if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto') {
2015
+ needLoopFix = false;
2016
+ }
2017
+ if (centeredSlides && needLoopFix) {
2018
+ const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
2019
+ swiper.loopFix({
2020
+ direction,
2021
+ slideTo: true,
2022
+ activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2023
+ slideRealIndex: direction === 'next' ? swiper.realIndex : undefined
2024
+ });
2025
+ }
2026
+ if (!centeredSlides && needLoopFix) {
2027
+ let direction;
2028
+ let nextSteps;
2029
+ let prevSteps;
2030
+ if (swiper.activeIndex < targetSlideIndex) {
2031
+ nextSteps = targetSlideIndex - swiper.activeIndex;
2032
+ prevSteps = swiper.activeIndex - (targetSlideIndex - totalSlides);
2037
2033
  } else {
2038
- newIndex = swiper.getSlideIndexByData(newIndex);
2034
+ prevSteps = swiper.activeIndex - targetSlideIndex;
2035
+ nextSteps = targetSlideIndex + totalSlides - swiper.activeIndex;
2039
2036
  }
2037
+ direction = nextSteps > prevSteps ? 'prev' : 'next';
2038
+ swiper.loopFixDot({
2039
+ direction,
2040
+ slideTo: true,
2041
+ activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2042
+ slideRealIndex: direction === 'next' ? swiper.realIndex : undefined,
2043
+ targetSlideIndex,
2044
+ newIndex: swiper.getSlideIndexByData(newIndex)
2045
+ });
2040
2046
  }
2047
+ newIndex = swiper.getSlideIndexByData(newIndex);
2041
2048
  }
2042
2049
  requestAnimationFrame(() => {
2043
2050
  swiper.slideTo(newIndex, speed, runCallbacks, internal);
@@ -2045,6 +2052,87 @@ var Swiper = (function () {
2045
2052
  return swiper;
2046
2053
  }
2047
2054
 
2055
+ function slideToLoopCenterSneakPeek(index, speed, runCallbacks, internal) {
2056
+ if (index === void 0) {
2057
+ index = 0;
2058
+ }
2059
+ if (runCallbacks === void 0) {
2060
+ runCallbacks = true;
2061
+ }
2062
+ if (typeof index === 'string') {
2063
+ const indexAsNumber = parseInt(index, 10);
2064
+ index = indexAsNumber;
2065
+ }
2066
+ const swiper = this;
2067
+ if (swiper.destroyed) return;
2068
+ if (typeof speed === 'undefined') {
2069
+ speed = swiper.params.speed;
2070
+ }
2071
+ let newIndex = index;
2072
+ if (swiper.params.loop) {
2073
+ swiper.slides;
2074
+ const totalSlides = swiper.slides.length;
2075
+ let targetSlideIndex;
2076
+ targetSlideIndex = swiper.getSlideIndexByData(newIndex);
2077
+ const cols = swiper.slides.length;
2078
+ const {
2079
+ centeredSlides
2080
+ } = swiper.params;
2081
+ let slidesPerView = swiper.params.slidesPerView;
2082
+ if (slidesPerView === 'auto') {
2083
+ slidesPerView = swiper.slidesPerViewDynamic();
2084
+ } else {
2085
+ slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2086
+ if (centeredSlides && slidesPerView % 2 === 0) {
2087
+ slidesPerView = slidesPerView + 1;
2088
+ }
2089
+ }
2090
+ if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto') ;
2091
+ const isSneakPeekCenter = swiper.params?.isSneakPeekCenter;
2092
+ if (isSneakPeekCenter) {
2093
+ let direction;
2094
+ let nextSteps;
2095
+ let prevSteps;
2096
+ if (swiper.activeIndex < targetSlideIndex) {
2097
+ nextSteps = targetSlideIndex - swiper.activeIndex;
2098
+ prevSteps = swiper.activeIndex - (targetSlideIndex - totalSlides);
2099
+ } else {
2100
+ prevSteps = swiper.activeIndex - targetSlideIndex;
2101
+ nextSteps = targetSlideIndex + totalSlides - swiper.activeIndex;
2102
+ }
2103
+ direction = nextSteps > prevSteps ? 'prev' : 'next';
2104
+ swiper.loopFixDot({
2105
+ direction,
2106
+ slideTo: true,
2107
+ activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
2108
+ slideRealIndex: direction === 'next' ? swiper.realIndex : undefined,
2109
+ targetSlideIndex,
2110
+ newIndex: swiper.getSlideIndexByData(newIndex)
2111
+ });
2112
+ }
2113
+ newIndex = swiper.getSlideIndexByData(newIndex);
2114
+ }
2115
+ swiper.slideTo(newIndex, speed, runCallbacks, internal);
2116
+ const slides = swiper.slides;
2117
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
2118
+ const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
2119
+ const swiperTranslate = JSON.parse(JSON.stringify(swiper.snapGrid[1]));
2120
+
2121
+ // Move last item to first position only if active slide is the first slide
2122
+ const lastSlide = slides[slides.length - 1];
2123
+ lastSlide.swiperLoopMoveDOM = true;
2124
+ swiper.slidesEl.prepend(lastSlide);
2125
+ lastSlide.swiperLoopMoveDOM = false;
2126
+ swiper.setTransition(0);
2127
+ swiper.setTranslate(-(swiperTranslate + gap));
2128
+ swiper.recalcSlides();
2129
+ swiper.updateSlides();
2130
+ swiper.setTransition(swiper.params.speed);
2131
+ swiper.setTranslate(-swiperTranslate);
2132
+ }
2133
+ return;
2134
+ }
2135
+
2048
2136
  /* eslint no-unused-vars: "off" */
2049
2137
  function slideNext(speed, runCallbacks, internal) {
2050
2138
  if (runCallbacks === void 0) {
@@ -2069,7 +2157,7 @@ var Swiper = (function () {
2069
2157
  if (params.loop) {
2070
2158
  if (animating && !isVirtual && params.loopPreventsSliding) return false;
2071
2159
 
2072
- // Check if loop is disabled
2160
+ // Kiểm tra xem loop bị disable không
2073
2161
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
2074
2162
  if (swiper.slides.length >= currentSlidesPerView) {
2075
2163
  swiper.loopFix({
@@ -2088,7 +2176,27 @@ var Swiper = (function () {
2088
2176
  if (params.rewind && swiper.isEnd) {
2089
2177
  return swiper.slideTo(0, speed, runCallbacks, internal);
2090
2178
  }
2091
- return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
2179
+ requestAnimationFrame(() => {
2180
+ swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
2181
+ const slides = swiper.slides;
2182
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1 && (swiper.activeIndex === slides.length - 1 || swiper.isEnd)) {
2183
+ const lastSnapGridIndex = swiper.snapGrid.length - 1;
2184
+ const gap = Math.abs(swiper.snapGrid[lastSnapGridIndex] - swiper.snapGrid[lastSnapGridIndex - 1]);
2185
+ const swiperTranslate = structuredClone(swiper.snapGrid[lastSnapGridIndex - 1]);
2186
+
2187
+ // Move first item to last position only if active slide is the last slide
2188
+ const firstSlide = slides[0];
2189
+ firstSlide.swiperLoopMoveDOM = true;
2190
+ swiper.slidesEl.append(firstSlide);
2191
+ firstSlide.swiperLoopMoveDOM = false;
2192
+ swiper.setTransition(0);
2193
+ swiper.setTranslate(-(swiperTranslate - gap));
2194
+ swiper.recalcSlides();
2195
+ swiper.updateSlides();
2196
+ swiper.setTransition(swiper.params.speed);
2197
+ swiper.setTranslate(-swiperTranslate);
2198
+ }
2199
+ });
2092
2200
  }
2093
2201
 
2094
2202
  /* eslint no-unused-vars: "off" */
@@ -2109,11 +2217,9 @@ var Swiper = (function () {
2109
2217
  if (typeof speed === 'undefined') {
2110
2218
  speed = swiper.params.speed;
2111
2219
  }
2112
- const isVirtual = swiper.virtual && params.virtual.enabled;
2220
+ swiper.virtual && params.virtual.enabled;
2113
2221
  if (params.loop) {
2114
- if (animating && !isVirtual && params.loopPreventsSliding) return false;
2115
-
2116
- // Check if loop is disabled
2222
+ // Kiểm tra xem loop bị disable không
2117
2223
  const currentSlidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10));
2118
2224
  if (swiper.slides.length >= currentSlidesPerView) {
2119
2225
  swiper.loopFix({
@@ -2162,7 +2268,27 @@ var Swiper = (function () {
2162
2268
  });
2163
2269
  return true;
2164
2270
  }
2165
- return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
2271
+ requestAnimationFrame(() => {
2272
+ swiper.slideTo(prevIndex, speed, runCallbacks, internal);
2273
+ const slides = swiper.slides;
2274
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1 && swiper.activeIndex === 0) {
2275
+ const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
2276
+ const swiperTranslate = JSON.parse(JSON.stringify(swiper.snapGrid[1]));
2277
+
2278
+ // Move last item to first position only if active slide is the first slide
2279
+ const lastSlide = slides[slides.length - 1];
2280
+ lastSlide.swiperLoopMoveDOM = true;
2281
+ swiper.slidesEl.prepend(lastSlide);
2282
+ lastSlide.swiperLoopMoveDOM = false;
2283
+ swiper.setTransition(0);
2284
+ swiper.setTranslate(-(swiperTranslate + gap));
2285
+ swiper.recalcSlides();
2286
+ swiper.updateSlides();
2287
+ swiper.setTransition(swiper.params.speed);
2288
+ swiper.setTranslate(-swiperTranslate);
2289
+ }
2290
+ });
2291
+ return;
2166
2292
  }
2167
2293
 
2168
2294
  /* eslint no-unused-vars: "off" */
@@ -2251,6 +2377,7 @@ var Swiper = (function () {
2251
2377
  var slide = {
2252
2378
  slideTo,
2253
2379
  slideToLoop,
2380
+ slideToLoopCenterSneakPeek,
2254
2381
  slideNext,
2255
2382
  slidePrev,
2256
2383
  slideReset,
@@ -2338,7 +2465,7 @@ var Swiper = (function () {
2338
2465
  const swiper = this;
2339
2466
  if (!swiper.params.loop) return;
2340
2467
 
2341
- // Disable loop mode if the number of slides is less than slidesPerView
2468
+ // Disable loop mode nếu số slides ít hơn slidesPerView
2342
2469
  const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2343
2470
  if (swiper.slides.length < currentSlidesPerView) {
2344
2471
  console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
@@ -2550,6 +2677,206 @@ var Swiper = (function () {
2550
2677
  swiper.emit('loopFix');
2551
2678
  }
2552
2679
 
2680
+ function loopFixDot(_temp) {
2681
+ let {
2682
+ slideRealIndex,
2683
+ slideTo = true,
2684
+ direction,
2685
+ activeSlideIndex,
2686
+ initial,
2687
+ targetSlideIndex,
2688
+ newIndex
2689
+ } = _temp === void 0 ? {} : _temp;
2690
+ const swiper = this;
2691
+ if (!swiper.params.loop) return;
2692
+
2693
+ // Disable loop mode nếu số slides ít hơn slidesPerView
2694
+ const currentSlidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
2695
+ if (swiper.slides.length < currentSlidesPerView) {
2696
+ console.warn('Swiper: Loop mode disabled - slides.length < slidesPerView');
2697
+ return;
2698
+ }
2699
+ swiper.emit('beforeLoopFix');
2700
+ const {
2701
+ slides,
2702
+ allowSlidePrev,
2703
+ allowSlideNext,
2704
+ slidesEl,
2705
+ params
2706
+ } = swiper;
2707
+ const targetData = slidesEl.children[targetSlideIndex].getAttribute('data-swiper-slide-index');
2708
+ const oldActiveData = Array.from(slidesEl.children).find(el => el.classList.contains(params.slideActiveClass)).getAttribute('data-swiper-slide-index');
2709
+ const {
2710
+ centeredSlides,
2711
+ initialSlide
2712
+ } = params;
2713
+ const swiperDataOldActiveIndex = slidesEl.children[swiper.activeIndex].getAttribute('data-swiper-slide-index');
2714
+ swiper.allowSlidePrev = true;
2715
+ swiper.allowSlideNext = true;
2716
+ let slidesPerView = params.slidesPerView;
2717
+ if (slidesPerView === 'auto') {
2718
+ slidesPerView = swiper.slidesPerViewDynamic();
2719
+ } else {
2720
+ slidesPerView = Math.ceil(parseFloat(params.slidesPerView, 10));
2721
+ if (centeredSlides && slidesPerView % 2 === 0) {
2722
+ slidesPerView = slidesPerView + 1;
2723
+ }
2724
+ }
2725
+ const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup;
2726
+ let loopedSlides = centeredSlides ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) : slidesPerGroup;
2727
+ if (loopedSlides % slidesPerGroup !== 0) {
2728
+ loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup;
2729
+ }
2730
+ loopedSlides += params.loopAdditionalSlides;
2731
+ swiper.loopedSlides = loopedSlides;
2732
+ if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
2733
+ 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');
2734
+ }
2735
+ const isNext = direction === 'next' || !direction;
2736
+ const isPrev = direction === 'prev' || !direction;
2737
+ let numberOfSlidesNeedClone = [];
2738
+ let slidesIndex = [];
2739
+ for (let i = 0; i < slidesEl.children.length; i++) {
2740
+ slidesIndex.push(slidesEl.children[i].getAttribute('data-swiper-slide-index'));
2741
+ }
2742
+ if (isPrev) {
2743
+ for (let i = targetSlideIndex; i < slidesEl.children.length; i++) {
2744
+ numberOfSlidesNeedClone.push(i);
2745
+ }
2746
+ } else if (isNext) {
2747
+ for (let i = 0; i < slidesPerView - (slidesEl.children.length - targetSlideIndex); i++) {
2748
+ numberOfSlidesNeedClone.push(i);
2749
+ }
2750
+ }
2751
+ const cols = slides.length;
2752
+ const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !centeredSlides;
2753
+ isInitialOverflow ? initialSlide : swiper.activeIndex;
2754
+ if (typeof activeSlideIndex === 'undefined') {
2755
+ activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass)));
2756
+ }
2757
+
2758
+ // Tạo DocumentFragment để chứa các slide clone
2759
+ const cloneFragment = document.createDocumentFragment();
2760
+
2761
+ // Clone các slide theo numberOfSlidesNeedClone (đã đảo ngược) và thêm vào fragment
2762
+ (isNext ? numberOfSlidesNeedClone : numberOfSlidesNeedClone.reverse()).forEach(index => {
2763
+ if (slides[index]) {
2764
+ const originalSlide = slides[index];
2765
+ const clonedSlide = originalSlide.cloneNode(true);
2766
+
2767
+ // Đánh dấu slide clone
2768
+ clonedSlide.setAttribute('data-swiper-clone', 'true');
2769
+ clonedSlide.classList.add('swiper-slide-clone');
2770
+
2771
+ // Thêm clone vào fragment
2772
+ cloneFragment.appendChild(clonedSlide);
2773
+ }
2774
+ });
2775
+ if (isPrev) {
2776
+ numberOfSlidesNeedClone.forEach(index => {
2777
+ const originalSlide = slides[index];
2778
+ originalSlide.swiperLoopMoveDOM = true;
2779
+ slidesEl.prepend(originalSlide);
2780
+ originalSlide.swiperLoopMoveDOM = false;
2781
+ });
2782
+ }
2783
+ if (isNext) {
2784
+ numberOfSlidesNeedClone.forEach(index => {
2785
+ const originalSlide = slides[index];
2786
+ originalSlide.swiperLoopMoveDOM = true;
2787
+ slidesEl.append(originalSlide);
2788
+ originalSlide.swiperLoopMoveDOM = false;
2789
+ });
2790
+ }
2791
+
2792
+ // Sắp xếp cloneFragment theo data-swiper-slide-index tăng dần
2793
+ const clonedSlides = Array.from(cloneFragment.children);
2794
+ clonedSlides.sort((a, b) => {
2795
+ const indexA = parseInt(a.getAttribute('data-swiper-slide-index')) || 0;
2796
+ const indexB = parseInt(b.getAttribute('data-swiper-slide-index')) || 0;
2797
+ return indexA - indexB;
2798
+ });
2799
+
2800
+ // Xóa tất cả children cũ và thêm lại theo thứ tự đã sắp xếp
2801
+ cloneFragment.innerHTML = '';
2802
+ clonedSlides.forEach(slide => {
2803
+ cloneFragment.appendChild(slide);
2804
+ });
2805
+
2806
+ // Thêm fragment vào vị trí phù hợp
2807
+ if (isPrev) {
2808
+ // Nếu là prev, thêm fragment vào cuối slidesEl
2809
+ slidesEl.appendChild(cloneFragment);
2810
+ } else if (isNext) {
2811
+ // Nếu là next, thêm fragment vào đầu slidesEl
2812
+ slidesEl.insertBefore(cloneFragment, slidesEl.firstChild);
2813
+ }
2814
+ swiper.recalcSlides();
2815
+ swiper.updateSlides();
2816
+
2817
+ // Tìm slide có data-swiper-slide-index tương ứng
2818
+ let oldActiveIndex = null;
2819
+ for (let i = 0; i < slidesEl.children.length; i++) {
2820
+ const child = slidesEl.children[i];
2821
+ if (child.getAttribute('data-swiper-slide-index') === swiperDataOldActiveIndex) {
2822
+ oldActiveIndex = i;
2823
+ break;
2824
+ }
2825
+ }
2826
+ if (slideTo && oldActiveIndex !== swiper.activeIndex) {
2827
+ swiper.slideTo(oldActiveIndex, 0);
2828
+ }
2829
+
2830
+ // Tìm vị trí slide cũ sau khi remove clone để set lại translate tạo hiệu ứng animate
2831
+ const skip = Math.min(swiper.params.slidesPerGroupSkip, newIndex);
2832
+ let snapIndex = skip + Math.floor((newIndex - skip) / swiper.params.slidesPerGroup);
2833
+ if (snapIndex >= swiper.snapGrid.length) snapIndex = swiper.snapGrid.length - 1;
2834
+ const translate = -swiper.snapGrid[snapIndex];
2835
+ if (translate === swiper.translate) {
2836
+ let oldActiveIndexAfterRemoveClone;
2837
+ for (let i = 0; i < slidesEl.children.length; i++) {
2838
+ const child = slidesEl.children[i];
2839
+ if (child.getAttribute('data-swiper-slide-index') === swiperDataOldActiveIndex) {
2840
+ oldActiveIndexAfterRemoveClone = i;
2841
+ break;
2842
+ }
2843
+ }
2844
+ const skip = Math.min(swiper.params.slidesPerGroupSkip, oldActiveIndexAfterRemoveClone);
2845
+ let snapIndex = skip + Math.floor((oldActiveIndexAfterRemoveClone - skip) / swiper.params.slidesPerGroup);
2846
+ if (snapIndex >= swiper.snapGrid.length) snapIndex = swiper.snapGrid.length - 1;
2847
+ const oldTranslate = -swiper.snapGrid[snapIndex];
2848
+ let updateTranslate;
2849
+ if (oldTranslate === swiper.translate) {
2850
+ updateTranslate = swiper.snapGrid[snapIndex > 0 ? snapIndex - 1 : swiper.snapGrid.length - 1];
2851
+ } else {
2852
+ updateTranslate = oldTranslate;
2853
+ }
2854
+ swiper.setTranslate(updateTranslate);
2855
+ }
2856
+ // Remove slide clone ra khỏi slidesEl sau khi slideTo hoàn thành
2857
+ const cloneSlides = slidesEl.querySelectorAll('[data-swiper-clone="true"]');
2858
+ cloneSlides.forEach(cloneSlide => {
2859
+ if (cloneSlide.parentNode) {
2860
+ cloneSlide.parentNode.removeChild(cloneSlide);
2861
+ }
2862
+ });
2863
+ swiper.recalcSlides();
2864
+ swiper.updateSlides();
2865
+ const targetDataIndex = Array.from(slidesEl.children).findIndex(el => el.getAttribute('data-swiper-slide-index') * 1 === targetData * 1);
2866
+ const oldDataIndex = Array.from(slidesEl.children).findIndex(el => el.getAttribute('data-swiper-slide-index') * 1 === oldActiveData * 1);
2867
+ const snapIndexNew = skip + Math.floor((targetDataIndex - skip) / swiper.params.slidesPerGroup);
2868
+ const snapIndexOld = skip + Math.floor((oldDataIndex - skip) / swiper.params.slidesPerGroup);
2869
+ if (slideTo && snapIndexNew === targetDataIndex) {
2870
+ const translateOld = -swiper.snapGrid[snapIndexOld > swiper.snapGrid.length - 1 ? snapIndexNew - 1 > swiper.snapGrid.length - 1 ? 0 : snapIndexNew - 1 : snapIndexOld];
2871
+ swiper.setTranslate(translateOld);
2872
+ }
2873
+ swiper.recalcSlides();
2874
+ swiper.updateSlides();
2875
+ swiper.allowSlidePrev = allowSlidePrev;
2876
+ swiper.allowSlideNext = allowSlideNext;
2877
+ swiper.emit('loopFixDot');
2878
+ }
2879
+
2553
2880
  function loopDestroy() {
2554
2881
  const swiper = this;
2555
2882
  const {
@@ -2576,6 +2903,7 @@ var Swiper = (function () {
2576
2903
  var loop = {
2577
2904
  loopCreate,
2578
2905
  loopFix,
2906
+ loopFixDot,
2579
2907
  loopDestroy
2580
2908
  };
2581
2909
 
@@ -3170,6 +3498,9 @@ var Swiper = (function () {
3170
3498
  swiper.slideTo(stopIndex);
3171
3499
  }
3172
3500
  }
3501
+ swiper.syncSneakPeekCenter({
3502
+ speed: swiper.params.speed
3503
+ });
3173
3504
  }
3174
3505
 
3175
3506
  function onResize() {
@@ -3711,6 +4042,7 @@ var Swiper = (function () {
3711
4042
  loopAddBlankSlides: true,
3712
4043
  loopAdditionalSlides: 0,
3713
4044
  loopPreventsSliding: true,
4045
+ isSneakPeekCenter: false,
3714
4046
  // rewind
3715
4047
  rewind: false,
3716
4048
  // Swiping/no swiping
@@ -4252,6 +4584,46 @@ var Swiper = (function () {
4252
4584
  });
4253
4585
  return true;
4254
4586
  }
4587
+ syncSneakPeekCenter(_temp) {
4588
+ let {
4589
+ speed = 0
4590
+ } = _temp === void 0 ? {} : _temp;
4591
+ const swiper = this;
4592
+ requestAnimationFrame(() => {
4593
+ const slides = swiper.slides;
4594
+ if (swiper.params?.isSneakPeekCenter && slides.length > 1) {
4595
+ const isFirstSlide = swiper.activeIndex === 0;
4596
+ const isLastSlide = swiper.activeIndex === slides.length - 1 || swiper.isEnd;
4597
+ const gap = Math.abs(swiper.snapGrid[1] - swiper.snapGrid[0]);
4598
+ const swiperTranslate = structuredClone(swiper.snapGrid[1]);
4599
+ if (isFirstSlide) {
4600
+ // Move last item to first position when at first slide
4601
+ const lastSlide = slides.at(-1);
4602
+ lastSlide.swiperLoopMoveDOM = true;
4603
+ swiper.slidesEl.prepend(lastSlide);
4604
+ lastSlide.swiperLoopMoveDOM = false;
4605
+ swiper.setTransition(0);
4606
+ swiper.setTranslate(-(swiperTranslate + gap));
4607
+ swiper.recalcSlides();
4608
+ swiper.updateSlides();
4609
+ swiper.setTransition(speed);
4610
+ swiper.setTranslate(-swiperTranslate);
4611
+ } else if (isLastSlide) {
4612
+ // Move first item to last position when at last slide
4613
+ const firstSlide = slides[0];
4614
+ firstSlide.swiperLoopMoveDOM = true;
4615
+ swiper.slidesEl.append(firstSlide);
4616
+ firstSlide.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
+ }
4624
+ }
4625
+ });
4626
+ }
4255
4627
  init(el) {
4256
4628
  const swiper = this;
4257
4629
  if (swiper.initialized) return swiper;
@@ -4313,6 +4685,7 @@ var Swiper = (function () {
4313
4685
  // Init Flag
4314
4686
  swiper.initialized = true;
4315
4687
  preload(swiper);
4688
+ swiper.syncSneakPeekCenter();
4316
4689
 
4317
4690
  // Emit
4318
4691
  swiper.emit('init');
package/swiper.less CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Swiper 0.0.7
2
+ * Swiper 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
  @themeColor: #007aff;
package/swiper.min.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Swiper 0.0.7
2
+ * Swiper 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
  @font-face{font-family:swiper-icons;src:url('data:application/font-woff;charset=utf-8;base64, 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');font-weight:400;font-style:normal}:root{--swiper-theme-color:#007aff}:host{position:relative;display:block;margin-left:auto;margin-right:auto;z-index:1}.swiper{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;list-style:none;padding:0;z-index:1;display:block}.swiper-vertical>.swiper-wrapper{flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:flex;transition-property:transform;transition-timing-function:var(--swiper-wrapper-transition-timing-function,initial);box-sizing:content-box}.swiper-android .swiper-slide,.swiper-ios .swiper-slide,.swiper-wrapper{transform:translate3d(0px,0,0)}.swiper-horizontal{touch-action:pan-y}.swiper-vertical{touch-action:pan-x}.swiper-slide{flex-shrink:0;width:100%;height:100%;position:relative;transition-property:transform;display:block}.swiper-slide-invisible-blank{visibility:hidden}.swiper-autoheight,.swiper-autoheight .swiper-slide{height:auto}.swiper-autoheight .swiper-wrapper{align-items:flex-start;transition-property:transform,height}.swiper-backface-hidden .swiper-slide{transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-3d.swiper-css-mode .swiper-wrapper{perspective:1200px}.swiper-3d .swiper-wrapper{transform-style:preserve-3d}.swiper-3d{perspective:1200px}.swiper-3d .swiper-cube-shadow,.swiper-3d .swiper-slide{transform-style:preserve-3d}.swiper-css-mode>.swiper-wrapper{overflow:auto;scrollbar-width:none;-ms-overflow-style:none}.swiper-css-mode>.swiper-wrapper::-webkit-scrollbar{display:none}.swiper-css-mode>.swiper-wrapper>.swiper-slide{scroll-snap-align:start start}.swiper-css-mode.swiper-horizontal>.swiper-wrapper{scroll-snap-type:x mandatory}.swiper-css-mode.swiper-vertical>.swiper-wrapper{scroll-snap-type:y mandatory}.swiper-css-mode.swiper-free-mode>.swiper-wrapper{scroll-snap-type:none}.swiper-css-mode.swiper-free-mode>.swiper-wrapper>.swiper-slide{scroll-snap-align:none}.swiper-css-mode.swiper-centered>.swiper-wrapper::before{content:'';flex-shrink:0;order:9999}.swiper-css-mode.swiper-centered>.swiper-wrapper>.swiper-slide{scroll-snap-align:center center;scroll-snap-stop:always}.swiper-css-mode.swiper-centered.swiper-horizontal>.swiper-wrapper>.swiper-slide:first-child{margin-inline-start:var(--swiper-centered-offset-before)}.swiper-css-mode.swiper-centered.swiper-horizontal>.swiper-wrapper::before{height:100%;min-height:1px;width:var(--swiper-centered-offset-after)}.swiper-css-mode.swiper-centered.swiper-vertical>.swiper-wrapper>.swiper-slide:first-child{margin-block-start:var(--swiper-centered-offset-before)}.swiper-css-mode.swiper-centered.swiper-vertical>.swiper-wrapper::before{width:100%;min-width:1px;height:var(--swiper-centered-offset-after)}.swiper-3d .swiper-slide-shadow,.swiper-3d .swiper-slide-shadow-bottom,.swiper-3d .swiper-slide-shadow-left,.swiper-3d .swiper-slide-shadow-right,.swiper-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-3d .swiper-slide-shadow{background:rgba(0,0,0,.15)}.swiper-3d .swiper-slide-shadow-left{background-image:linear-gradient(to left,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-right{background-image:linear-gradient(to right,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-top{background-image:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-bottom{background-image:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;transform-origin:50%;box-sizing:border-box;border:4px solid var(--swiper-preloader-color,var(--swiper-theme-color));border-radius:50%;border-top-color:transparent}.swiper-watch-progress .swiper-slide-visible .swiper-lazy-preloader,.swiper:not(.swiper-watch-progress) .swiper-lazy-preloader{animation:swiper-preloader-spin 1s infinite linear}.swiper-lazy-preloader-white{--swiper-preloader-color:#fff}.swiper-lazy-preloader-black{--swiper-preloader-color:#000}@keyframes swiper-preloader-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}