Browse Source

Bug Fix: Failed to sync indices when using arrow keys (#489).

NaotoshiFujita 3 years ago
parent
commit
b14d83b120

+ 1 - 1
dist/js/splide-renderer.min.js

@@ -1,6 +1,6 @@
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 3.2.5
+ * Version  : 3.2.6
  * License  : MIT
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  * Copyright: 2021 Naotoshi Fujita
  */
  */

+ 34 - 26
dist/js/splide.cjs.js

@@ -1,6 +1,6 @@
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 3.2.5
+ * Version  : 3.2.6
  * License  : MIT
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  * Copyright: 2021 Naotoshi Fujita
  */
  */
@@ -1352,11 +1352,7 @@ function Controller(Splide2, Components2, options) {
         index = getPrev(true);
         index = getPrev(true);
       }
       }
     } else {
     } else {
-      if (isLoop) {
-        index = clamp(control, -perPage, slideCount + perPage - 1);
-      } else {
-        index = clamp(control, 0, getEnd());
-      }
+      index = isLoop ? control : clamp(control, 0, getEnd());
     }
     }
     return index;
     return index;
   }
   }
@@ -1897,12 +1893,11 @@ function Keyboard(Splide2, Components2, options) {
   const { root } = Components2.Elements;
   const { root } = Components2.Elements;
   const { resolve } = Components2.Direction;
   const { resolve } = Components2.Direction;
   let target;
   let target;
+  let disabled;
   function mount() {
   function mount() {
     init();
     init();
-    on(EVENT_UPDATED, () => {
-      destroy();
-      init();
-    });
+    on(EVENT_UPDATED, onUpdated);
+    on(EVENT_MOVE, onMove);
   }
   }
   function init() {
   function init() {
     const { keyboard = "global" } = options;
     const { keyboard = "global" } = options;
@@ -1922,13 +1917,25 @@ function Keyboard(Splide2, Components2, options) {
       removeAttribute(target, TAB_INDEX);
       removeAttribute(target, TAB_INDEX);
     }
     }
   }
   }
+  function onMove() {
+    disabled = true;
+    nextTick(() => {
+      disabled = false;
+    });
+  }
+  function onUpdated() {
+    destroy();
+    init();
+  }
   function onKeydown(e) {
   function onKeydown(e) {
-    const { key } = e;
-    const normalizedKey = includes(IE_ARROW_KEYS, key) ? `Arrow${key}` : key;
-    if (normalizedKey === resolve("ArrowLeft")) {
-      Splide2.go("<");
-    } else if (normalizedKey === resolve("ArrowRight")) {
-      Splide2.go(">");
+    if (!disabled) {
+      const { key } = e;
+      const normalizedKey = includes(IE_ARROW_KEYS, key) ? `Arrow${key}` : key;
+      if (normalizedKey === resolve("ArrowLeft")) {
+        Splide2.go("<");
+      } else if (normalizedKey === resolve("ArrowRight")) {
+        Splide2.go(">");
+      }
     }
     }
   }
   }
   return {
   return {
@@ -2120,10 +2127,12 @@ function Sync(Splide2, Components2, options) {
   function sync() {
   function sync() {
     const processed = [];
     const processed = [];
     splides.concat(Splide2).forEach((splide, index, instances) => {
     splides.concat(Splide2).forEach((splide, index, instances) => {
-      EventInterface(splide).on(EVENT_MOVE, (index2, prev, dest) => {
+      const { on } = EventInterface(splide);
+      on(EVENT_MOVE, (index2, prev, dest) => {
         instances.forEach((instance) => {
         instances.forEach((instance) => {
           if (instance !== splide && !includes(processed, splide)) {
           if (instance !== splide && !includes(processed, splide)) {
             processed.push(instance);
             processed.push(instance);
+            instance.Components.Move.cancel();
             instance.go(instance.is(LOOP) ? dest : index2);
             instance.go(instance.is(LOOP) ? dest : index2);
           }
           }
         });
         });
@@ -2448,7 +2457,8 @@ class Style {
   buildSelectors(selectors) {
   buildSelectors(selectors) {
     let css = "";
     let css = "";
     forOwn(selectors, (styles, selector) => {
     forOwn(selectors, (styles, selector) => {
-      css += `#${this.id} ${selector} {`;
+      selector = `#${this.id} ${selector}`.trim();
+      css += `${selector} {`;
       forOwn(styles, (value, prop) => {
       forOwn(styles, (value, prop) => {
         if (value || value === 0) {
         if (value || value === 0) {
           css += `${prop}: ${value};`;
           css += `${prop}: ${value};`;
@@ -2528,6 +2538,9 @@ class SplideRenderer {
     const selector = `.${CLASS_LIST}`;
     const selector = `.${CLASS_LIST}`;
     this.breakpoints.forEach(([width, options]) => {
     this.breakpoints.forEach(([width, options]) => {
       Style2.rule(selector, "transform", this.buildTranslate(options), width);
       Style2.rule(selector, "transform", this.buildTranslate(options), width);
+      if (!this.cssSlideHeight(options)) {
+        Style2.rule(selector, "aspect-ratio", this.cssAspectRatio(options), width);
+      }
     });
     });
   }
   }
   registerSlideStyles() {
   registerSlideStyles() {
@@ -2535,13 +2548,8 @@ class SplideRenderer {
     const selector = `.${CLASS_SLIDE}`;
     const selector = `.${CLASS_SLIDE}`;
     this.breakpoints.forEach(([width, options]) => {
     this.breakpoints.forEach(([width, options]) => {
       Style2.rule(selector, "width", this.cssSlideWidth(options), width);
       Style2.rule(selector, "width", this.cssSlideWidth(options), width);
+      Style2.rule(selector, "height", this.cssSlideHeight(options) || "100%", width);
       Style2.rule(selector, this.resolve("marginRight"), unit(options.gap) || "0px", width);
       Style2.rule(selector, this.resolve("marginRight"), unit(options.gap) || "0px", width);
-      const height = this.cssSlideHeight(options);
-      if (height) {
-        Style2.rule(selector, "height", height, width);
-      } else {
-        Style2.rule(selector, "padding-top", this.cssSlidePadding(options), width);
-      }
       Style2.rule(`${selector} > img`, "display", options.cover ? "none" : "inline", width);
       Style2.rule(`${selector} > img`, "display", options.cover ? "none" : "inline", width);
     });
     });
   }
   }
@@ -2626,9 +2634,9 @@ class SplideRenderer {
     const gap = unit(options.gap);
     const gap = unit(options.gap);
     return `calc((100%${gap && ` + ${gap}`})/${options.perPage || 1}${gap && ` - ${gap}`})`;
     return `calc((100%${gap && ` + ${gap}`})/${options.perPage || 1}${gap && ` - ${gap}`})`;
   }
   }
-  cssSlidePadding(options) {
+  cssAspectRatio(options) {
     const { heightRatio } = options;
     const { heightRatio } = options;
-    return heightRatio ? `${heightRatio * 100}%` : "";
+    return heightRatio ? `${1 / heightRatio}` : "";
   }
   }
   buildCssValue(value, unit2) {
   buildCssValue(value, unit2) {
     return `${value}${unit2}`;
     return `${value}${unit2}`;

+ 34 - 26
dist/js/splide.esm.js

@@ -1,6 +1,6 @@
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 3.2.5
+ * Version  : 3.2.6
  * License  : MIT
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  * Copyright: 2021 Naotoshi Fujita
  */
  */
@@ -1348,11 +1348,7 @@ function Controller(Splide2, Components2, options) {
         index = getPrev(true);
         index = getPrev(true);
       }
       }
     } else {
     } else {
-      if (isLoop) {
-        index = clamp(control, -perPage, slideCount + perPage - 1);
-      } else {
-        index = clamp(control, 0, getEnd());
-      }
+      index = isLoop ? control : clamp(control, 0, getEnd());
     }
     }
     return index;
     return index;
   }
   }
@@ -1893,12 +1889,11 @@ function Keyboard(Splide2, Components2, options) {
   const { root } = Components2.Elements;
   const { root } = Components2.Elements;
   const { resolve } = Components2.Direction;
   const { resolve } = Components2.Direction;
   let target;
   let target;
+  let disabled;
   function mount() {
   function mount() {
     init();
     init();
-    on(EVENT_UPDATED, () => {
-      destroy();
-      init();
-    });
+    on(EVENT_UPDATED, onUpdated);
+    on(EVENT_MOVE, onMove);
   }
   }
   function init() {
   function init() {
     const { keyboard = "global" } = options;
     const { keyboard = "global" } = options;
@@ -1918,13 +1913,25 @@ function Keyboard(Splide2, Components2, options) {
       removeAttribute(target, TAB_INDEX);
       removeAttribute(target, TAB_INDEX);
     }
     }
   }
   }
+  function onMove() {
+    disabled = true;
+    nextTick(() => {
+      disabled = false;
+    });
+  }
+  function onUpdated() {
+    destroy();
+    init();
+  }
   function onKeydown(e) {
   function onKeydown(e) {
-    const { key } = e;
-    const normalizedKey = includes(IE_ARROW_KEYS, key) ? `Arrow${key}` : key;
-    if (normalizedKey === resolve("ArrowLeft")) {
-      Splide2.go("<");
-    } else if (normalizedKey === resolve("ArrowRight")) {
-      Splide2.go(">");
+    if (!disabled) {
+      const { key } = e;
+      const normalizedKey = includes(IE_ARROW_KEYS, key) ? `Arrow${key}` : key;
+      if (normalizedKey === resolve("ArrowLeft")) {
+        Splide2.go("<");
+      } else if (normalizedKey === resolve("ArrowRight")) {
+        Splide2.go(">");
+      }
     }
     }
   }
   }
   return {
   return {
@@ -2116,10 +2123,12 @@ function Sync(Splide2, Components2, options) {
   function sync() {
   function sync() {
     const processed = [];
     const processed = [];
     splides.concat(Splide2).forEach((splide, index, instances) => {
     splides.concat(Splide2).forEach((splide, index, instances) => {
-      EventInterface(splide).on(EVENT_MOVE, (index2, prev, dest) => {
+      const { on } = EventInterface(splide);
+      on(EVENT_MOVE, (index2, prev, dest) => {
         instances.forEach((instance) => {
         instances.forEach((instance) => {
           if (instance !== splide && !includes(processed, splide)) {
           if (instance !== splide && !includes(processed, splide)) {
             processed.push(instance);
             processed.push(instance);
+            instance.Components.Move.cancel();
             instance.go(instance.is(LOOP) ? dest : index2);
             instance.go(instance.is(LOOP) ? dest : index2);
           }
           }
         });
         });
@@ -2444,7 +2453,8 @@ class Style {
   buildSelectors(selectors) {
   buildSelectors(selectors) {
     let css = "";
     let css = "";
     forOwn(selectors, (styles, selector) => {
     forOwn(selectors, (styles, selector) => {
-      css += `#${this.id} ${selector} {`;
+      selector = `#${this.id} ${selector}`.trim();
+      css += `${selector} {`;
       forOwn(styles, (value, prop) => {
       forOwn(styles, (value, prop) => {
         if (value || value === 0) {
         if (value || value === 0) {
           css += `${prop}: ${value};`;
           css += `${prop}: ${value};`;
@@ -2524,6 +2534,9 @@ class SplideRenderer {
     const selector = `.${CLASS_LIST}`;
     const selector = `.${CLASS_LIST}`;
     this.breakpoints.forEach(([width, options]) => {
     this.breakpoints.forEach(([width, options]) => {
       Style2.rule(selector, "transform", this.buildTranslate(options), width);
       Style2.rule(selector, "transform", this.buildTranslate(options), width);
+      if (!this.cssSlideHeight(options)) {
+        Style2.rule(selector, "aspect-ratio", this.cssAspectRatio(options), width);
+      }
     });
     });
   }
   }
   registerSlideStyles() {
   registerSlideStyles() {
@@ -2531,13 +2544,8 @@ class SplideRenderer {
     const selector = `.${CLASS_SLIDE}`;
     const selector = `.${CLASS_SLIDE}`;
     this.breakpoints.forEach(([width, options]) => {
     this.breakpoints.forEach(([width, options]) => {
       Style2.rule(selector, "width", this.cssSlideWidth(options), width);
       Style2.rule(selector, "width", this.cssSlideWidth(options), width);
+      Style2.rule(selector, "height", this.cssSlideHeight(options) || "100%", width);
       Style2.rule(selector, this.resolve("marginRight"), unit(options.gap) || "0px", width);
       Style2.rule(selector, this.resolve("marginRight"), unit(options.gap) || "0px", width);
-      const height = this.cssSlideHeight(options);
-      if (height) {
-        Style2.rule(selector, "height", height, width);
-      } else {
-        Style2.rule(selector, "padding-top", this.cssSlidePadding(options), width);
-      }
       Style2.rule(`${selector} > img`, "display", options.cover ? "none" : "inline", width);
       Style2.rule(`${selector} > img`, "display", options.cover ? "none" : "inline", width);
     });
     });
   }
   }
@@ -2622,9 +2630,9 @@ class SplideRenderer {
     const gap = unit(options.gap);
     const gap = unit(options.gap);
     return `calc((100%${gap && ` + ${gap}`})/${options.perPage || 1}${gap && ` - ${gap}`})`;
     return `calc((100%${gap && ` + ${gap}`})/${options.perPage || 1}${gap && ` - ${gap}`})`;
   }
   }
-  cssSlidePadding(options) {
+  cssAspectRatio(options) {
     const { heightRatio } = options;
     const { heightRatio } = options;
-    return heightRatio ? `${heightRatio * 100}%` : "";
+    return heightRatio ? `${1 / heightRatio}` : "";
   }
   }
   buildCssValue(value, unit2) {
   buildCssValue(value, unit2) {
     return `${value}${unit2}`;
     return `${value}${unit2}`;

+ 39 - 26
dist/js/splide.js

@@ -4,7 +4,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
 
 /*!
 /*!
  * Splide.js
  * Splide.js
- * Version  : 3.2.5
+ * Version  : 3.2.6
  * License  : MIT
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  * Copyright: 2021 Naotoshi Fujita
  */
  */
@@ -1609,11 +1609,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
           index = getPrev(true);
           index = getPrev(true);
         }
         }
       } else {
       } else {
-        if (isLoop) {
-          index = clamp(control, -perPage, slideCount + perPage - 1);
-        } else {
-          index = clamp(control, 0, getEnd());
-        }
+        index = isLoop ? control : clamp(control, 0, getEnd());
       }
       }
 
 
       return index;
       return index;
@@ -2295,13 +2291,12 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     var root = Components2.Elements.root;
     var root = Components2.Elements.root;
     var resolve = Components2.Direction.resolve;
     var resolve = Components2.Direction.resolve;
     var target;
     var target;
+    var disabled;
 
 
     function mount() {
     function mount() {
       init();
       init();
-      on(EVENT_UPDATED, function () {
-        destroy();
-        init();
-      });
+      on(EVENT_UPDATED, onUpdated);
+      on(EVENT_MOVE, onMove);
     }
     }
 
 
     function init() {
     function init() {
@@ -2328,14 +2323,28 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       }
       }
     }
     }
 
 
+    function onMove() {
+      disabled = true;
+      nextTick(function () {
+        disabled = false;
+      });
+    }
+
+    function onUpdated() {
+      destroy();
+      init();
+    }
+
     function onKeydown(e) {
     function onKeydown(e) {
-      var key = e.key;
-      var normalizedKey = includes(IE_ARROW_KEYS, key) ? "Arrow" + key : key;
+      if (!disabled) {
+        var key = e.key;
+        var normalizedKey = includes(IE_ARROW_KEYS, key) ? "Arrow" + key : key;
 
 
-      if (normalizedKey === resolve("ArrowLeft")) {
-        Splide2.go("<");
-      } else if (normalizedKey === resolve("ArrowRight")) {
-        Splide2.go(">");
+        if (normalizedKey === resolve("ArrowLeft")) {
+          Splide2.go("<");
+        } else if (normalizedKey === resolve("ArrowRight")) {
+          Splide2.go(">");
+        }
       }
       }
     }
     }
 
 
@@ -2598,10 +2607,14 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function sync() {
     function sync() {
       var processed = [];
       var processed = [];
       splides.concat(Splide2).forEach(function (splide, index, instances) {
       splides.concat(Splide2).forEach(function (splide, index, instances) {
-        EventInterface(splide).on(EVENT_MOVE, function (index2, prev, dest) {
+        var _EventInterface16 = EventInterface(splide),
+            on = _EventInterface16.on;
+
+        on(EVENT_MOVE, function (index2, prev, dest) {
           instances.forEach(function (instance) {
           instances.forEach(function (instance) {
             if (instance !== splide && !includes(processed, splide)) {
             if (instance !== splide && !includes(processed, splide)) {
               processed.push(instance);
               processed.push(instance);
+              instance.Components.Move.cancel();
               instance.go(instance.is(LOOP) ? dest : index2);
               instance.go(instance.is(LOOP) ? dest : index2);
             }
             }
           });
           });
@@ -2611,9 +2624,9 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
     }
 
 
     function navigate() {
     function navigate() {
-      var _EventInterface16 = EventInterface(Splide2),
-          on = _EventInterface16.on,
-          emit = _EventInterface16.emit;
+      var _EventInterface17 = EventInterface(Splide2),
+          on = _EventInterface17.on,
+          emit = _EventInterface17.emit;
 
 
       on(EVENT_CLICK, onClick);
       on(EVENT_CLICK, onClick);
       on(EVENT_SLIDE_KEYDOWN, onKeydown);
       on(EVENT_SLIDE_KEYDOWN, onKeydown);
@@ -2644,8 +2657,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
   }
   }
 
 
   function Wheel(Splide2, Components2, options) {
   function Wheel(Splide2, Components2, options) {
-    var _EventInterface17 = EventInterface(Splide2),
-        bind = _EventInterface17.bind;
+    var _EventInterface18 = EventInterface(Splide2),
+        bind = _EventInterface18.bind;
 
 
     function mount() {
     function mount() {
       if (options.wheel) {
       if (options.wheel) {
@@ -2723,8 +2736,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
   };
   };
 
 
   function Fade(Splide2, Components2, options) {
   function Fade(Splide2, Components2, options) {
-    var _EventInterface18 = EventInterface(Splide2),
-        on = _EventInterface18.on;
+    var _EventInterface19 = EventInterface(Splide2),
+        on = _EventInterface19.on;
 
 
     function mount() {
     function mount() {
       on([EVENT_MOUNTED, EVENT_REFRESH], function () {
       on([EVENT_MOUNTED, EVENT_REFRESH], function () {
@@ -2751,8 +2764,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
   }
   }
 
 
   function Slide(Splide2, Components2, options) {
   function Slide(Splide2, Components2, options) {
-    var _EventInterface19 = EventInterface(Splide2),
-        bind = _EventInterface19.bind;
+    var _EventInterface20 = EventInterface(Splide2),
+        bind = _EventInterface20.bind;
 
 
     var Move = Components2.Move,
     var Move = Components2.Move,
         Controller = Components2.Controller;
         Controller = Components2.Controller;

File diff suppressed because it is too large
+ 0 - 0
dist/js/splide.js.map


File diff suppressed because it is too large
+ 1 - 1
dist/js/splide.min.js


BIN
dist/js/splide.min.js.gz


+ 1 - 1
dist/types/components/Controller/Controller.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Controller.d.ts","sourceRoot":"","sources":["Controller.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI9E;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,EAAE,CAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IACvF,MAAM,CAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IACnH,OAAO,CAAE,WAAW,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACzC,OAAO,CAAE,WAAW,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACzC,MAAM,IAAI,MAAM,CAAC;IACjB,QAAQ,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI,CAAC;IAChC,QAAQ,CAAE,IAAI,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACnC,OAAO,CAAE,IAAI,EAAE,MAAM,GAAI,MAAM,CAAC;IAChC,MAAM,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,CAAC;IAChC,MAAM,CAAE,QAAQ,EAAE,MAAM,GAAI,MAAM,CAAC;IACnC,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,mBAAmB,CA0U1G"}
+{"version":3,"file":"Controller.d.ts","sourceRoot":"","sources":["Controller.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI9E;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,EAAE,CAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IACvF,MAAM,CAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IACnH,OAAO,CAAE,WAAW,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACzC,OAAO,CAAE,WAAW,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACzC,MAAM,IAAI,MAAM,CAAC;IACjB,QAAQ,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI,CAAC;IAChC,QAAQ,CAAE,IAAI,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACnC,OAAO,CAAE,IAAI,EAAE,MAAM,GAAI,MAAM,CAAC;IAChC,MAAM,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,CAAC;IAChC,MAAM,CAAE,QAAQ,EAAE,MAAM,GAAI,MAAM,CAAC;IACnC,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,mBAAmB,CAsU1G"}

+ 1 - 1
dist/types/components/Keyboard/Keyboard.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Keyboard.d.ts","sourceRoot":"","sources":["Keyboard.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAIjE;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;CACvD;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,iBAAiB,CAuEtG"}
+{"version":3,"file":"Keyboard.d.ts","sourceRoot":"","sources":["Keyboard.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAIjE;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;CACvD;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,iBAAiB,CA4FtG"}

+ 1 - 1
dist/types/components/Sync/Sync.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Sync.d.ts","sourceRoot":"","sources":["Sync.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKjE;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;CACnD;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,aAAa,CA4F9F"}
+{"version":3,"file":"Sync.d.ts","sourceRoot":"","sources":["Sync.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKjE;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;CACnD;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,aAAa,CA+F9F"}

+ 3 - 3
dist/types/renderer/SplideRenderer/SplideRenderer.d.ts

@@ -174,13 +174,13 @@ export declare class SplideRenderer {
      */
      */
     private cssSlideSize;
     private cssSlideSize;
     /**
     /**
-     * Returns the paddingTop value to simulate the height of each slide.
+     * Returns the aspectRatio value to simulate the `heightRatio` option.
      *
      *
      * @param options - Options.
      * @param options - Options.
      *
      *
-     * @return paddingTop in the CSS format.
+     * @return aspectRatio in the CSS format.
      */
      */
-    private cssSlidePadding;
+    private cssAspectRatio;
     /**
     /**
      * Builds the css value by the provided value and unit.
      * Builds the css value by the provided value and unit.
      *
      *

File diff suppressed because it is too large
+ 0 - 0
dist/types/renderer/SplideRenderer/SplideRenderer.d.ts.map


+ 1 - 1
dist/types/renderer/Style/Style.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Style.d.ts","sourceRoot":"","sources":["Style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAUtC;;;;GAIG;AACH,qBAAa,KAAK;IAChB;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAE5B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC;;;;;OAKG;gBACU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAKzC;;;;;;;OAOG;IACH,IAAI,CAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAI,IAAI;IAOzF;;;;OAIG;IACH,KAAK,IAAI,MAAM;IAoBf;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;CAiBvB"}
+{"version":3,"file":"Style.d.ts","sourceRoot":"","sources":["Style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAUtC;;;;GAIG;AACH,qBAAa,KAAK;IAChB;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAE5B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC;;;;;OAKG;gBACU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAKzC;;;;;;;OAOG;IACH,IAAI,CAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAI,IAAI;IAOzF;;;;OAIG;IACH,KAAK,IAAI,MAAM;IAoBf;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;CAkBvB"}

+ 1 - 1
dist/types/test/utils/utils.d.ts

@@ -51,6 +51,6 @@ export declare function keydown(key: string, target?: Window | Element): void;
  *
  *
  * @return A Promise instance.
  * @return A Promise instance.
  */
  */
-export declare function wait(duration: number): Promise<void>;
+export declare function wait(duration?: number): Promise<void>;
 export {};
 export {};
 //# sourceMappingURL=../../../../src/js/test/utils/utils.d.ts.map
 //# sourceMappingURL=../../../../src/js/test/utils/utils.d.ts.map

+ 1 - 1
dist/types/test/utils/utils.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAa,aAAa,EAAE,MAAM,aAAa,CAAC;AAIvD,UAAU,QAAS,SAAQ,aAAa;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAE,OAAO,GAAE,OAAY,EAAE,IAAI,GAAE,QAAa,GAAI,MAAM,CAqFzE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAE,GAAG,EAAE,WAAW,GAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAgBhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAClB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,EACnC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,GAAQ,EACd,aAAa,GAAE,SAAc,GAC5B,KAAK,CAUP;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,OAAgB,GAAI,IAAI,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAE,QAAQ,EAAE,MAAM,GAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
+{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAa,aAAa,EAAE,MAAM,aAAa,CAAC;AAIvD,UAAU,QAAS,SAAQ,aAAa;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAE,OAAO,GAAE,OAAY,EAAE,IAAI,GAAE,QAAa,GAAI,MAAM,CAqFzE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAE,GAAG,EAAE,WAAW,GAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAgBhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAClB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,EACnC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,GAAQ,EACd,aAAa,GAAE,SAAc,GAC5B,KAAK,CAUP;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,OAAgB,GAAI,IAAI,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAE,QAAQ,SAAI,GAAI,OAAO,CAAC,IAAI,CAAC,CAIlD"}

+ 1 - 1
package-lock.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@splidejs/splide",
   "name": "@splidejs/splide",
-  "version": "3.2.5",
+  "version": "3.2.6",
   "lockfileVersion": 1,
   "lockfileVersion": 1,
   "requires": true,
   "requires": true,
   "dependencies": {
   "dependencies": {

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@splidejs/splide",
   "name": "@splidejs/splide",
-  "version": "3.2.5",
+  "version": "3.2.6",
   "description": "Splide is a lightweight, flexible and accessible slider/carousel. No dependencies, no Lighthouse errors.",
   "description": "Splide is a lightweight, flexible and accessible slider/carousel. No dependencies, no Lighthouse errors.",
   "author": "Naotoshi Fujita",
   "author": "Naotoshi Fujita",
   "license": "MIT",
   "license": "MIT",

+ 1 - 5
src/js/components/Controller/Controller.ts

@@ -158,11 +158,7 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
         index = getPrev( true );
         index = getPrev( true );
       }
       }
     } else {
     } else {
-      if ( isLoop ) {
-        index = clamp( control, -perPage, slideCount + perPage - 1 );
-      } else {
-        index = clamp( control, 0, getEnd() );
-      }
+      index = isLoop ? control : clamp( control, 0, getEnd() );
     }
     }
 
 
     return index;
     return index;

+ 35 - 14
src/js/components/Keyboard/Keyboard.ts

@@ -1,9 +1,9 @@
 import { TAB_INDEX } from '../../constants/attributes';
 import { TAB_INDEX } from '../../constants/attributes';
-import { EVENT_UPDATED } from '../../constants/events';
+import { EVENT_UPDATED, EVENT_MOVE } from '../../constants/events';
 import { EventInterface } from '../../constructors';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
 import { BaseComponent, Components, Options } from '../../types';
-import { includes, isHTMLElement, removeAttribute, setAttribute } from '../../utils';
+import { includes, isHTMLElement, nextTick, removeAttribute, setAttribute } from '../../utils';
 
 
 
 
 /**
 /**
@@ -42,16 +42,18 @@ export function Keyboard( Splide: Splide, Components: Components, options: Optio
    */
    */
   let target: Window | HTMLElement;
   let target: Window | HTMLElement;
 
 
+  /**
+   * Indicates whether the component is currently disabled or not.
+   */
+  let disabled: boolean;
+
   /**
   /**
    * Called when the component is mounted.
    * Called when the component is mounted.
    */
    */
   function mount(): void {
   function mount(): void {
     init();
     init();
-
-    on( EVENT_UPDATED, () => {
-      destroy();
-      init();
-    } );
+    on( EVENT_UPDATED, onUpdated );
+    on( EVENT_MOVE, onMove );
   }
   }
 
 
   /**
   /**
@@ -75,7 +77,7 @@ export function Keyboard( Splide: Splide, Components: Components, options: Optio
   /**
   /**
    * Destroys the component.
    * Destroys the component.
    */
    */
-  function destroy() {
+  function destroy(): void {
     unbind( target, 'keydown' );
     unbind( target, 'keydown' );
 
 
     if ( isHTMLElement( target ) ) {
     if ( isHTMLElement( target ) ) {
@@ -83,19 +85,38 @@ export function Keyboard( Splide: Splide, Components: Components, options: Optio
     }
     }
   }
   }
 
 
+  /**
+   * Called when the slider moves.
+   * To avoid the slider from moving twice, wait for a tick.
+   */
+  function onMove(): void {
+    disabled = true;
+    nextTick( () => { disabled = false } );
+  }
+
+  /**
+   * Called when options are update.
+   */
+  function onUpdated(): void {
+    destroy();
+    init();
+  }
+
   /**
   /**
    * Called when any key is pressed on the target.
    * Called when any key is pressed on the target.
    *
    *
    * @param e - A KeyboardEvent object.
    * @param e - A KeyboardEvent object.
    */
    */
   function onKeydown( e: KeyboardEvent ): void {
   function onKeydown( e: KeyboardEvent ): void {
-    const { key } = e;
-    const normalizedKey = includes( IE_ARROW_KEYS, key ) ? `Arrow${ key }` : key;
+    if ( ! disabled ) {
+      const { key } = e;
+      const normalizedKey = includes( IE_ARROW_KEYS, key ) ? `Arrow${ key }` : key;
 
 
-    if ( normalizedKey === resolve( 'ArrowLeft' ) ) {
-      Splide.go( '<' );
-    } else if ( normalizedKey === resolve( 'ArrowRight' ) ) {
-      Splide.go( '>' );
+      if ( normalizedKey === resolve( 'ArrowLeft' ) ) {
+        Splide.go( '<' );
+      } else if ( normalizedKey === resolve( 'ArrowRight' ) ) {
+        Splide.go( '>' );
+      }
     }
     }
   }
   }
 
 

+ 27 - 5
src/js/components/Keyboard/test/general.test.ts

@@ -1,57 +1,75 @@
 import { RTL, TTB } from '../../../constants/directions';
 import { RTL, TTB } from '../../../constants/directions';
-import { init, keydown } from '../../../test';
+import { init, keydown, wait } from '../../../test';
 
 
 
 
 describe( 'Keyboard', () => {
 describe( 'Keyboard', () => {
-  test( 'can control the slider by keyboards.', () => {
+  test( 'can control the slider by keyboards.', async () => {
     const splide = init( { speed: 0 } );
     const splide = init( { speed: 0 } );
 
 
     keydown( 'ArrowRight' );
     keydown( 'ArrowRight' );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
 
 
+    await wait();
+
     keydown( 'ArrowRight' );
     keydown( 'ArrowRight' );
     expect( splide.index ).toBe( 2 );
     expect( splide.index ).toBe( 2 );
 
 
+    await wait();
+
     keydown( 'ArrowLeft' );
     keydown( 'ArrowLeft' );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
 
 
+    await wait();
+
     keydown( 'ArrowLeft' );
     keydown( 'ArrowLeft' );
     expect( splide.index ).toBe( 0 );
     expect( splide.index ).toBe( 0 );
   } );
   } );
 
 
-  test( 'can control the slider by keyboards in TTB mode.', () => {
+  test( 'can control the slider by keyboards in TTB mode.', async () => {
     const splide = init( { direction: TTB, height: 1, speed: 0 } );
     const splide = init( { direction: TTB, height: 1, speed: 0 } );
 
 
     keydown( 'ArrowDown' );
     keydown( 'ArrowDown' );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
 
 
+    await wait();
+
     keydown( 'ArrowDown' );
     keydown( 'ArrowDown' );
     expect( splide.index ).toBe( 2 );
     expect( splide.index ).toBe( 2 );
 
 
+    await wait();
+
     keydown( 'ArrowUp' );
     keydown( 'ArrowUp' );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
 
 
+    await wait();
+
     keydown( 'ArrowUp' );
     keydown( 'ArrowUp' );
     expect( splide.index ).toBe( 0 );
     expect( splide.index ).toBe( 0 );
   } );
   } );
 
 
-  test( 'can control the slider by keyboards in RTL mode.', () => {
+  test( 'can control the slider by keyboards in RTL mode.', async () => {
     const splide = init( { direction: RTL, speed: 0 } );
     const splide = init( { direction: RTL, speed: 0 } );
 
 
     keydown( 'ArrowLeft' );
     keydown( 'ArrowLeft' );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
 
 
+    await wait();
+
     keydown( 'ArrowLeft' );
     keydown( 'ArrowLeft' );
     expect( splide.index ).toBe( 2 );
     expect( splide.index ).toBe( 2 );
 
 
+    await wait();
+
     keydown( 'ArrowRight' );
     keydown( 'ArrowRight' );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
 
 
+    await wait();
+
     keydown( 'ArrowRight' );
     keydown( 'ArrowRight' );
     expect( splide.index ).toBe( 0 );
     expect( splide.index ).toBe( 0 );
   } );
   } );
 
 
-  test( 'can control the slider by keyboards only when the slider has focus in the `focused` mode.', () => {
+  test( 'can control the slider by keyboards only when the slider has focus in the `focused` mode.', async () => {
     const splide = init( { keyboard: 'focused', speed: 0 } );
     const splide = init( { keyboard: 'focused', speed: 0 } );
     const { root } = splide;
     const { root } = splide;
 
 
@@ -60,8 +78,12 @@ describe( 'Keyboard', () => {
     keydown( 'ArrowRight' );
     keydown( 'ArrowRight' );
     expect( splide.index ).toBe( 0 );
     expect( splide.index ).toBe( 0 );
 
 
+    await wait();
+
     splide.root.focus();
     splide.root.focus();
 
 
+    await wait();
+
     keydown( 'ArrowRight', root );
     keydown( 'ArrowRight', root );
     expect( splide.index ).toBe( 1 );
     expect( splide.index ).toBe( 1 );
   } );
   } );

+ 4 - 1
src/js/components/Sync/Sync.ts

@@ -72,10 +72,13 @@ export function Sync( Splide: Splide, Components: Components, options: Options )
     const processed: Splide[] = [];
     const processed: Splide[] = [];
 
 
     splides.concat( Splide ).forEach( ( splide, index, instances ) => {
     splides.concat( Splide ).forEach( ( splide, index, instances ) => {
-      EventInterface( splide ).on( EVENT_MOVE, ( index, prev, dest ) => {
+      const { on } = EventInterface( splide );
+
+      on( EVENT_MOVE, ( index, prev, dest ) => {
         instances.forEach( instance => {
         instances.forEach( instance => {
           if ( instance !== splide && ! includes( processed, splide ) ) {
           if ( instance !== splide && ! includes( processed, splide ) ) {
             processed.push( instance );
             processed.push( instance );
+            instance.Components.Move.cancel();
             instance.go( instance.is( LOOP ) ? dest : index );
             instance.go( instance.is( LOOP ) ? dest : index );
           }
           }
         } );
         } );

+ 10 - 9
src/js/test/php/examples/sync.php

@@ -21,7 +21,7 @@ $settings = get_settings();
         type       : 'loop',
         type       : 'loop',
         heightRatio: 0.3,
         heightRatio: 0.3,
         perPage    : 2,
         perPage    : 2,
-        // cover      : true,
+        // waitForTransition: false,
 
 
         breakpoints: {
         breakpoints: {
           1000: {
           1000: {
@@ -31,14 +31,15 @@ $settings = get_settings();
       } );
       } );
 
 
       var splide02 = new Splide( '#splide02', {
       var splide02 = new Splide( '#splide02', {
-        width       : 600,
-        fixedWidth  : 100,
-        fixedHeight : 56,
-        gap         : '.7em',
-        isNavigation: true,
-        focus       : 'center',
-        pagination  : false,
-        // type        : 'loop',
+        width            : 600,
+        fixedWidth       : 100,
+        fixedHeight      : 56,
+        gap              : '.7em',
+        isNavigation     : true,
+        focus            : 'center',
+        pagination       : false,
+        rewind           : true,
+        waitForTransition: true,
         dragMinThreshold: {
         dragMinThreshold: {
           mouse: 10,
           mouse: 10,
           touch: 10,
           touch: 10,

+ 1 - 1
src/js/test/utils/utils.ts

@@ -176,7 +176,7 @@ export function keydown( key: string, target: Window | Element = window ): void
  *
  *
  * @return A Promise instance.
  * @return A Promise instance.
  */
  */
-export function wait( duration: number ): Promise<void> {
+export function wait( duration = 0 ): Promise<void> {
   return new Promise( resolve => {
   return new Promise( resolve => {
     setTimeout( resolve, duration );
     setTimeout( resolve, duration );
   } );
   } );

Some files were not shown because too many files changed in this diff