Browse Source

Improve the drag performance. Add the `useScroll` option.

NaotoshiFujita 3 years ago
parent
commit
56ca26def8
67 changed files with 821 additions and 1058 deletions
  1. 1 1
      dist/js/splide-renderer.min.js
  2. 156 165
      dist/js/splide.cjs.js
  3. 156 165
      dist/js/splide.esm.js
  4. 184 202
      dist/js/splide.js
  5. 0 0
      dist/js/splide.js.map
  6. 2 2
      dist/js/splide.min.js
  7. BIN
      dist/js/splide.min.js.gz
  8. 1 1
      dist/types/components/Clones/Clones.d.ts.map
  9. 2 0
      dist/types/components/Controller/Controller.d.ts
  10. 1 1
      dist/types/components/Controller/Controller.d.ts.map
  11. 1 1
      dist/types/components/Drag/Drag.d.ts.map
  12. 1 1
      dist/types/components/Elements/Elements.d.ts.map
  13. 1 1
      dist/types/components/Layout/Layout.d.ts.map
  14. 1 0
      dist/types/components/Move/Move.d.ts
  15. 1 1
      dist/types/components/Move/Move.d.ts.map
  16. 2 2
      dist/types/components/Scroll/Scroll.d.ts
  17. 1 1
      dist/types/components/Scroll/Scroll.d.ts.map
  18. 2 2
      dist/types/components/Slides/Slide.d.ts
  19. 1 1
      dist/types/components/Slides/Slide.d.ts.map
  20. 1 1
      dist/types/components/Slides/Slides.d.ts
  21. 1 1
      dist/types/components/Slides/Slides.d.ts.map
  22. 0 19
      dist/types/components/Style/Style.d.ts
  23. 0 1
      dist/types/components/Style/Style.d.ts.map
  24. 1 2
      dist/types/components/index.d.ts
  25. 1 1
      dist/types/components/index.d.ts.map
  26. 0 16
      dist/types/test/utils/utils.d.ts
  27. 1 1
      dist/types/test/utils/utils.d.ts.map
  28. 1 1
      dist/types/transitions/Fade/Fade.d.ts.map
  29. 4 0
      dist/types/types/options.d.ts
  30. 0 0
      dist/types/types/options.d.ts.map
  31. 3 9
      dist/types/utils/dom/style/style.d.ts
  32. 1 1
      dist/types/utils/dom/style/style.d.ts.map
  33. 1 1
      package-lock.json
  34. 1 1
      package.json
  35. 1 1
      src/js/components/Autoplay/Autoplay.ts
  36. 2 1
      src/js/components/Clones/Clones.ts
  37. 54 16
      src/js/components/Controller/Controller.ts
  38. 1 1
      src/js/components/Cover/Cover.ts
  39. 0 32
      src/js/components/Cover/test/general.test.ts
  40. 5 17
      src/js/components/Drag/Drag.ts
  41. 17 1
      src/js/components/Elements/Elements.ts
  42. 10 12
      src/js/components/Layout/Layout.ts
  43. 11 12
      src/js/components/Layout/test/general.test.ts
  44. 24 50
      src/js/components/Layout/test/ltr.test.ts
  45. 3 5
      src/js/components/Layout/test/rtl.test.ts
  46. 20 29
      src/js/components/Layout/test/ttb.test.ts
  47. 18 3
      src/js/components/Move/Move.ts
  48. 3 4
      src/js/components/Move/test/general.test.ts
  49. 24 7
      src/js/components/Scroll/Scroll.ts
  50. 9 6
      src/js/components/Slides/Slide.ts
  51. 8 5
      src/js/components/Slides/Slides.ts
  52. 0 99
      src/js/components/Style/Style.ts
  53. 0 59
      src/js/components/Style/test/general.test.ts
  54. 1 2
      src/js/components/index.ts
  55. 1 1
      src/js/constants/defaults.ts
  56. 2 2
      src/js/constructors/EventBus/test/key.test.ts
  57. 3 3
      src/js/test/assets/css/styles.css
  58. 0 1
      src/js/test/php/examples/breakpoints.php
  59. 23 19
      src/js/test/php/examples/default.php
  60. 3 2
      src/js/test/php/examples/sync.php
  61. 0 26
      src/js/test/utils/utils.ts
  62. 4 7
      src/js/transitions/Fade/Fade.ts
  63. 2 2
      src/js/transitions/Slide/Slide.ts
  64. 5 0
      src/js/types/options.ts
  65. 1 1
      src/js/utils/dom/display/display.ts
  66. 10 2
      src/js/utils/dom/style/style.test.ts
  67. 26 28
      src/js/utils/dom/style/style.ts

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


+ 156 - 165
dist/js/splide.cjs.js

@@ -1,6 +1,6 @@
 /*!
  * Splide.js
- * Version  : 3.0.9
+ * Version  : 3.1.0
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  */
@@ -183,19 +183,21 @@ function create(tag, attrs, parent) {
   return elm;
 }
 
-function style(elm, styles) {
-  if (isString(styles)) {
-    return getComputedStyle(elm)[styles];
+function style(elm, prop, value) {
+  if (isUndefined(value)) {
+    return getComputedStyle(elm)[prop];
   }
-  forOwn(styles, (value, key) => {
-    if (!isNull(value)) {
-      elm.style[key] = `${value}`;
+  if (!isNull(value)) {
+    const { style: style2 } = elm;
+    value = `${value}`;
+    if (style2[prop] !== value) {
+      style2[prop] = value;
     }
-  });
+  }
 }
 
 function display(elm, display2) {
-  style(elm, { display: display2 });
+  style(elm, "display", display2);
 }
 
 function getAttribute(elm, attr) {
@@ -679,6 +681,9 @@ function Elements(Splide2, Components2, options) {
     on(EVENT_UPDATED, update);
   }
   function destroy() {
+    [root, track, list].forEach((elm) => {
+      removeAttribute(elm, "style");
+    });
     empty(slides);
     removeClass(root, classes);
   }
@@ -738,42 +743,6 @@ function Elements(Splide2, Components2, options) {
   });
 }
 
-function Style$1() {
-  let style;
-  let sheet;
-  function mount() {
-    style = create("style", {}, document.head);
-    sheet = style.sheet;
-  }
-  function destroy() {
-    remove(style);
-    sheet = null;
-  }
-  function rule(selector, prop, value) {
-    const { cssRules } = sheet;
-    const cssRule = find(cssRules, (cssRule2) => isCSSStyleRule(cssRule2) && cssRule2.selectorText === selector) || cssRules[sheet.insertRule(`${selector}{}`, 0)];
-    if (isCSSStyleRule(cssRule)) {
-      const { style: style2 } = cssRule;
-      value = `${value}`;
-      if (style2[prop] !== value) {
-        style2[prop] = value;
-      }
-    }
-  }
-  function ruleBy(target, prop, value) {
-    rule(`#${isHTMLElement(target) ? target.id : target}`, prop, value);
-  }
-  function isCSSStyleRule(cssRule) {
-    return cssRule instanceof CSSStyleRule;
-  }
-  return {
-    mount,
-    destroy,
-    rule,
-    ruleBy
-  };
-}
-
 const ROLE = "role";
 const ARIA_CONTROLS = "aria-controls";
 const ARIA_CURRENT = "aria-current";
@@ -802,6 +771,7 @@ function Slide$1(Splide2, index, slideIndex, slide) {
   const { Components, root, options } = Splide2;
   const { isNavigation, updateOnMove } = options;
   const { resolve } = Components.Direction;
+  const styles = getAttribute(slide, "style");
   const isClone = slideIndex > -1;
   const container = child(slide, `.${CLASS_CONTAINER}`);
   const focusableNodes = options.focusableNodes && queryAll(slide, options.focusableNodes);
@@ -834,6 +804,7 @@ function Slide$1(Splide2, index, slideIndex, slide) {
     destroyEvents();
     removeClass(slide, STATUS_CLASSES);
     removeAttribute(slide, ALL_ATTRIBUTES);
+    setAttribute(slide, "style", styles);
   }
   function onMove(next, prev, dest) {
     if (!destroyed) {
@@ -875,9 +846,8 @@ function Slide$1(Splide2, index, slideIndex, slide) {
       emit(visible ? EVENT_VISIBLE : EVENT_HIDDEN, this);
     }
   }
-  function rule(prop, value, useContainer) {
-    const selector = `#${slide.id}${container && useContainer ? ` > .${CLASS_CONTAINER}` : ""}`;
-    Components.Style.rule(selector, prop, value);
+  function style$1(prop, value, useContainer) {
+    style(useContainer && container || slide, prop, value);
   }
   function isActive() {
     return Splide2.index === index;
@@ -907,7 +877,7 @@ function Slide$1(Splide2, index, slideIndex, slide) {
     isClone,
     mount,
     destroy,
-    rule,
+    style: style$1,
     isWithin
   };
 }
@@ -919,6 +889,9 @@ function Slides(Splide2, Components2, options) {
   function mount() {
     init();
     on(EVENT_REFRESH, refresh);
+    on([EVENT_MOUNTED, EVENT_REFRESH], () => {
+      Slides2.sort((Slide1, Slide2) => Slide1.index - Slide2.index);
+    });
   }
   function init() {
     slides.forEach((slide, index) => {
@@ -976,9 +949,9 @@ function Slides(Splide2, Components2, options) {
   function filter(matcher) {
     return Slides2.filter(isFunction(matcher) ? matcher : (Slide2) => isString(matcher) ? matches(Slide2.slide, matcher) : includes(toArray(matcher), Slide2.index));
   }
-  function rule(prop, value, useContainer) {
+  function style(prop, value, useContainer) {
     forEach$1((Slide2) => {
-      Slide2.rule(prop, value, useContainer);
+      Slide2.style(prop, value, useContainer);
     });
   }
   function observeImages(elm, callback) {
@@ -1013,85 +986,15 @@ function Slides(Splide2, Components2, options) {
     remove: remove$1,
     forEach: forEach$1,
     filter,
-    rule,
+    style,
     getLength,
     isEnough
   };
 }
 
-function Clones(Splide2, Components2, options) {
-  const { on, emit } = EventInterface(Splide2);
-  const { Elements, Slides } = Components2;
-  const { resolve } = Components2.Direction;
-  const clones = [];
-  let cloneCount;
-  function mount() {
-    init();
-    on(EVENT_REFRESH, refresh);
-    on([EVENT_UPDATED, EVENT_RESIZE], observe);
-  }
-  function init() {
-    if (cloneCount = computeCloneCount()) {
-      generate(cloneCount);
-    }
-  }
-  function destroy() {
-    remove(clones);
-    empty(clones);
-  }
-  function refresh() {
-    destroy();
-    init();
-  }
-  function observe() {
-    if (cloneCount !== computeCloneCount()) {
-      emit(EVENT_REFRESH);
-    }
-  }
-  function generate(count) {
-    const slides = Slides.get().slice();
-    const { length } = slides;
-    if (length) {
-      while (slides.length < count) {
-        push(slides, slides);
-      }
-      push(slides.slice(-count), slides.slice(0, count)).forEach((Slide, index) => {
-        const isHead = index < count;
-        const clone = cloneDeep(Slide.slide, index);
-        isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);
-        push(clones, clone);
-        Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);
-      });
-    }
-  }
-  function cloneDeep(elm, index) {
-    const clone = elm.cloneNode(true);
-    addClass(clone, options.classes.clone);
-    clone.id = `${Splide2.root.id}-clone${pad(index + 1)}`;
-    return clone;
-  }
-  function computeCloneCount() {
-    let { clones: clones2 } = options;
-    if (!Splide2.is(LOOP)) {
-      clones2 = 0;
-    } else if (!clones2) {
-      const fixedSize = measure(Elements.list, options[resolve("fixedWidth")]);
-      const fixedCount = fixedSize && ceil(rect(Elements.track)[resolve("width")] / fixedSize);
-      const baseCount = fixedCount || options[resolve("autoWidth")] && Splide2.length || options.perPage;
-      clones2 = baseCount * (options.drag ? (options.flickMaxPages || 1) + 1 : 2);
-    }
-    return clones2;
-  }
-  return {
-    mount,
-    destroy
-  };
-}
-
 function Layout(Splide2, Components2, options) {
   const { on, bind, emit } = EventInterface(Splide2);
   const { Slides } = Components2;
-  const { ruleBy } = Components2.Style;
   const { resolve } = Components2.Direction;
   const { track, list } = Components2.Elements;
   const { getAt } = Slides;
@@ -1104,21 +1007,20 @@ function Layout(Splide2, Components2, options) {
   }
   function init() {
     vertical = options.direction === TTB;
-    ruleBy(Splide2.root, "maxWidth", unit(options.width));
-    ruleBy(track, resolve("paddingLeft"), cssPadding(false));
-    ruleBy(track, resolve("paddingRight"), cssPadding(true));
-    Slides.rule(resolve("marginRight"), unit(options.gap));
-    Slides.rule("width", cssSlideWidth());
-    setSlidesHeight();
+    style(Splide2.root, "maxWidth", unit(options.width));
+    style(track, resolve("paddingLeft"), cssPadding(false));
+    style(track, resolve("paddingRight"), cssPadding(true));
     resize();
   }
   function resize() {
-    ruleBy(track, "height", cssTrackHeight());
-    options.heightRatio && setSlidesHeight();
+    style(track, "height", cssTrackHeight());
+    Slides.style(resolve("marginRight"), unit(options.gap));
+    Slides.style("width", cssSlideWidth() || null);
+    setSlidesHeight();
     emit(EVENT_RESIZED);
   }
   function setSlidesHeight() {
-    Slides.rule("height", cssSlideHeight(), true);
+    Slides.style("height", cssSlideHeight(), true);
   }
   function cssPadding(right) {
     const { padding } = options;
@@ -1183,6 +1085,76 @@ function Layout(Splide2, Components2, options) {
   };
 }
 
+function Clones(Splide2, Components2, options) {
+  const { on, emit } = EventInterface(Splide2);
+  const { Elements, Slides } = Components2;
+  const { resolve } = Components2.Direction;
+  const clones = [];
+  let cloneCount;
+  function mount() {
+    init();
+    on(EVENT_REFRESH, refresh);
+    on([EVENT_UPDATED, EVENT_RESIZE], observe);
+  }
+  function init() {
+    if (cloneCount = computeCloneCount()) {
+      generate(cloneCount);
+      emit(EVENT_RESIZE);
+    }
+  }
+  function destroy() {
+    remove(clones);
+    empty(clones);
+  }
+  function refresh() {
+    destroy();
+    init();
+  }
+  function observe() {
+    if (cloneCount < computeCloneCount()) {
+      emit(EVENT_REFRESH);
+    }
+  }
+  function generate(count) {
+    const slides = Slides.get().slice();
+    const { length } = slides;
+    if (length) {
+      while (slides.length < count) {
+        push(slides, slides);
+      }
+      push(slides.slice(-count), slides.slice(0, count)).forEach((Slide, index) => {
+        const isHead = index < count;
+        const clone = cloneDeep(Slide.slide, index);
+        isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);
+        push(clones, clone);
+        Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);
+      });
+    }
+  }
+  function cloneDeep(elm, index) {
+    const clone = elm.cloneNode(true);
+    addClass(clone, options.classes.clone);
+    clone.id = `${Splide2.root.id}-clone${pad(index + 1)}`;
+    return clone;
+  }
+  function computeCloneCount() {
+    let { clones: clones2 } = options;
+    if (!Splide2.is(LOOP)) {
+      clones2 = 0;
+    } else if (!clones2) {
+      const fixedSize = measure(Elements.list, options[resolve("fixedWidth")]);
+      const fixedCount = fixedSize && ceil(rect(Elements.track)[resolve("width")] / fixedSize);
+      const baseCount = fixedCount || options[resolve("autoWidth")] && Splide2.length || options.perPage;
+      clones2 = baseCount * (options.drag ? (options.flickMaxPages || 1) + 1 : 2);
+    }
+    return clones2;
+  }
+  return {
+    mount,
+    destroy
+  };
+}
+
 function Move(Splide2, Components2, options) {
   const { on, emit } = EventInterface(Splide2);
   const { slideSize, getPadding, totalSize, listSize, sliderSize } = Components2.Layout;
@@ -1235,13 +1207,17 @@ function Move(Splide2, Components2, options) {
       const exceededMin = exceededLimit(false, position) && diff < 0;
       const exceededMax = exceededLimit(true, position) && diff > 0;
       if (exceededMin || exceededMax) {
-        const excess = position - getLimit(exceededMax);
-        const size = sliderSize();
-        position -= sign(excess) * size * ceil(abs(excess) / size);
+        position = shift(position, exceededMax);
       }
     }
     return position;
   }
+  function shift(position, backwards) {
+    const excess = position - getLimit(backwards);
+    const size = sliderSize();
+    position -= sign(excess) * size * ceil(abs(excess) / size);
+    return position;
+  }
   function cancel() {
     waiting = false;
     translate(getPosition());
@@ -1299,6 +1275,7 @@ function Move(Splide2, Components2, options) {
     move,
     jump,
     translate,
+    shift,
     cancel,
     toIndex,
     toPosition,
@@ -1315,6 +1292,7 @@ function Controller(Splide2, Components2, options) {
   const { getPosition, getLimit } = Move;
   const { isEnough, getLength } = Components2.Slides;
   const isLoop = Splide2.is(LOOP);
+  const isSlide = Splide2.is(SLIDE);
   let currIndex = options.start || 0;
   let prevIndex = currIndex;
   let slideCount;
@@ -1323,7 +1301,6 @@ function Controller(Splide2, Components2, options) {
   function mount() {
     init();
     on([EVENT_UPDATED, EVENT_REFRESH], init, DEFAULT_EVENT_PRIORITY - 1);
-    on(EVENT_SCROLLED, reindex, 0);
   }
   function init() {
     slideCount = getLength(true);
@@ -1331,17 +1308,25 @@ function Controller(Splide2, Components2, options) {
     perPage = options.perPage;
     currIndex = clamp(currIndex, 0, slideCount - 1);
   }
-  function reindex() {
-    setIndex(Move.toIndex(getPosition()));
-  }
   function go(control, allowSameIndex, callback) {
     const dest = parse(control);
-    const index = loop(dest);
-    if (index > -1 && !Move.isBusy() && (allowSameIndex || index !== currIndex)) {
-      setIndex(index);
-      Move.move(dest, index, prevIndex, callback);
+    if (options.useScroll) {
+      scroll(dest, true, true, options.speed, callback);
+    } else {
+      const index = loop(dest);
+      if (index > -1 && !Move.isBusy() && (allowSameIndex || index !== currIndex)) {
+        setIndex(index);
+        Move.move(dest, index, prevIndex, callback);
+      }
     }
   }
+  function scroll(destination, useIndex, snap, duration, callback) {
+    const dest = useIndex ? destination : toDest(destination);
+    Components2.Scroll.scroll(useIndex || snap ? Move.toPosition(dest, true) : destination, duration, () => {
+      setIndex(Move.toIndex(Move.getPosition()));
+      callback && callback();
+    });
+  }
   function parse(control) {
     let index = currIndex;
     if (isString(control)) {
@@ -1371,7 +1356,7 @@ function Controller(Splide2, Components2, options) {
   function getAdjacent(prev, destination) {
     const number = perMove || hasFocus() ? 1 : perPage;
     const dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex);
-    if (dest === -1 && Splide2.is(SLIDE)) {
+    if (dest === -1 && isSlide) {
       if (!approximatelyEqual(getPosition(), getLimit(!prev), 1)) {
         return prev ? 0 : getEnd();
       }
@@ -1426,6 +1411,10 @@ function Controller(Splide2, Components2, options) {
     }
     return index;
   }
+  function toDest(destination) {
+    const closest = Move.toIndex(destination);
+    return isSlide ? clamp(closest, 0, getEnd()) : closest;
+  }
   function setIndex(index) {
     if (index !== currIndex) {
       prevIndex = currIndex;
@@ -1441,6 +1430,7 @@ function Controller(Splide2, Components2, options) {
   return {
     mount,
     go,
+    scroll,
     getNext,
     getPrev,
     getEnd,
@@ -1448,6 +1438,7 @@ function Controller(Splide2, Components2, options) {
     getIndex,
     toIndex,
     toPage,
+    toDest,
     hasFocus
   };
 }
@@ -1608,7 +1599,7 @@ function Autoplay(Splide2, Components2, options) {
   function update(rate) {
     const { bar } = Elements;
     if (bar) {
-      style(bar, { width: `${rate * 100}%` });
+      style(bar, "width", `${rate * 100}%`);
     }
     emit(EVENT_AUTOPLAY_PLAYING, rate);
   }
@@ -1643,7 +1634,7 @@ function Cover(Splide2, Components2, options) {
     });
   }
   function toggle(cover, img, Slide) {
-    Slide.rule("background", cover ? `center/cover no-repeat url("${img.src}")` : "", true);
+    Slide.style("background", cover ? `center/cover no-repeat url("${img.src}")` : "", true);
     display(img, cover ? "none" : "");
   }
   return {
@@ -1663,14 +1654,16 @@ function Scroll(Splide2, Components2, options) {
   const { Move } = Components2;
   const { getPosition, getLimit, exceededLimit } = Move;
   let interval;
+  let scrollCallback;
   function mount() {
     on(EVENT_MOVE, clear);
     on([EVENT_UPDATED, EVENT_REFRESH], cancel);
   }
-  function scroll(destination, duration, suppressConstraint) {
+  function scroll(destination, duration, callback, suppressConstraint) {
     const start = getPosition();
     let friction = 1;
     duration = duration || computeDuration(abs(destination - start));
+    scrollCallback = callback;
     clear();
     interval = RequestInterval(duration, onScrolled, (rate) => {
       const position = getPosition();
@@ -1688,9 +1681,15 @@ function Scroll(Splide2, Components2, options) {
     interval.start();
   }
   function bounce(backwards) {
-    scroll(getLimit(!backwards), BOUNCE_DURATION, true);
+    scroll(getLimit(!backwards), BOUNCE_DURATION, null, true);
   }
   function onScrolled() {
+    const position = getPosition();
+    const index = Move.toIndex(position);
+    if (!between(index, 0, Splide2.length - 1)) {
+      Move.translate(Move.shift(position, index > 0), true);
+    }
+    scrollCallback && scrollCallback();
     emit(EVENT_SCROLLED);
   }
   function computeDuration(distance) {
@@ -1732,7 +1731,6 @@ function Drag(Splide2, Components2, options) {
   const { resolve, orient } = Components2.Direction;
   const { getPosition, exceededLimit } = Move;
   const listenerOptions = { passive: false, capture: true };
-  const isSlide = Splide2.is(SLIDE);
   let basePosition;
   let baseEvent;
   let prevBaseEvent;
@@ -1748,6 +1746,7 @@ function Drag(Splide2, Components2, options) {
     bind(track, POINTER_UP_EVENTS, noop, listenerOptions);
     bind(track, POINTER_DOWN_EVENTS, onPointerDown, listenerOptions);
     bind(track, "click", onClick, { capture: true });
+    bind(track, "dragstart", prevent);
     on([EVENT_MOUNTED, EVENT_UPDATED], init);
   }
   function init() {
@@ -1808,11 +1807,11 @@ function Drag(Splide2, Components2, options) {
         const velocity = computeVelocity(e);
         const destination = computeDestination(velocity);
         if (isFree) {
-          Scroll.scroll(destination);
+          Controller.scroll(destination);
         } else if (Splide2.is(FADE)) {
           Controller.go(Splide2.index + orient(sign(velocity)));
         } else {
-          Controller.go(computeIndex(destination), true);
+          Controller.go(Controller.toDest(destination), true);
         }
         prevent(e);
       }
@@ -1850,10 +1849,6 @@ function Drag(Splide2, Components2, options) {
   function computeDestination(velocity) {
     return getPosition() + sign(velocity) * min(abs(velocity) * (options.flickPower || 600), isFree ? Infinity : Components2.Layout.listSize() * (options.flickMaxPages || 1));
   }
-  function computeIndex(destination) {
-    const dest = Move.toIndex(destination);
-    return isSlide ? clamp(dest, 0, Controller.getEnd()) : dest;
-  }
   function coordOf(e, orthogonal) {
     return (isTouchEvent(e) ? e.touches[0] : e)[`page${resolve(orthogonal ? "Y" : "X")}`];
   }
@@ -1864,7 +1859,7 @@ function Drag(Splide2, Components2, options) {
     return e.timeStamp;
   }
   function constrain(diff) {
-    return diff / (hasExceeded && isSlide ? FRICTION : 1);
+    return diff / (hasExceeded && Splide2.is(SLIDE) ? FRICTION : 1);
   }
   function disable(value) {
     disabled = value;
@@ -2164,10 +2159,9 @@ var ComponentConstructors = /*#__PURE__*/Object.freeze({
   Options: Options,
   Direction: Direction,
   Elements: Elements,
-  Style: Style$1,
   Slides: Slides,
-  Clones: Clones,
   Layout: Layout,
+  Clones: Clones,
   Move: Move,
   Controller: Controller,
   Arrows: Arrows,
@@ -2204,7 +2198,7 @@ const DEFAULTS = {
   pauseOnHover: true,
   pauseOnFocus: true,
   resetProgress: true,
-  easing: "cubic-bezier(.42,.65,.27,.99)",
+  easing: "cubic-bezier(0.25, 1, 0.5, 1)",
   drag: true,
   direction: "ltr",
   slideFocus: true,
@@ -2216,22 +2210,19 @@ const DEFAULTS = {
 
 function Fade(Splide2, Components2, options) {
   const { on } = EventInterface(Splide2);
-  const { ruleBy } = Components2.Style;
   function mount() {
     on([EVENT_MOUNTED, EVENT_REFRESH], () => {
       nextTick(() => {
-        Components2.Slides.forEach((Slide) => {
-          ruleBy(Slide.slide, "transition", `opacity ${options.speed}ms ${options.easing}`);
-        });
+        Components2.Slides.style("transition", `opacity ${options.speed}ms ${options.easing}`);
       });
     });
   }
   function start(index, done) {
     const { track } = Components2.Elements;
-    ruleBy(track, "height", unit(rect(track).height));
+    style(track, "height", unit(rect(track).height));
     nextTick(() => {
       done();
-      ruleBy(track, "height", "");
+      style(track, "height", "");
     });
   }
   return {
@@ -2282,7 +2273,7 @@ function Slide(Splide2, Components2, options) {
     return options.speed;
   }
   function apply(transition) {
-    Components2.Style.ruleBy(list, "transition", transition);
+    style(list, "transition", transition);
   }
   return {
     mount,

+ 156 - 165
dist/js/splide.esm.js

@@ -1,6 +1,6 @@
 /*!
  * Splide.js
- * Version  : 3.0.9
+ * Version  : 3.1.0
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  */
@@ -179,19 +179,21 @@ function create(tag, attrs, parent) {
   return elm;
 }
 
-function style(elm, styles) {
-  if (isString(styles)) {
-    return getComputedStyle(elm)[styles];
+function style(elm, prop, value) {
+  if (isUndefined(value)) {
+    return getComputedStyle(elm)[prop];
   }
-  forOwn(styles, (value, key) => {
-    if (!isNull(value)) {
-      elm.style[key] = `${value}`;
+  if (!isNull(value)) {
+    const { style: style2 } = elm;
+    value = `${value}`;
+    if (style2[prop] !== value) {
+      style2[prop] = value;
     }
-  });
+  }
 }
 
 function display(elm, display2) {
-  style(elm, { display: display2 });
+  style(elm, "display", display2);
 }
 
 function getAttribute(elm, attr) {
@@ -675,6 +677,9 @@ function Elements(Splide2, Components2, options) {
     on(EVENT_UPDATED, update);
   }
   function destroy() {
+    [root, track, list].forEach((elm) => {
+      removeAttribute(elm, "style");
+    });
     empty(slides);
     removeClass(root, classes);
   }
@@ -734,42 +739,6 @@ function Elements(Splide2, Components2, options) {
   });
 }
 
-function Style$1() {
-  let style;
-  let sheet;
-  function mount() {
-    style = create("style", {}, document.head);
-    sheet = style.sheet;
-  }
-  function destroy() {
-    remove(style);
-    sheet = null;
-  }
-  function rule(selector, prop, value) {
-    const { cssRules } = sheet;
-    const cssRule = find(cssRules, (cssRule2) => isCSSStyleRule(cssRule2) && cssRule2.selectorText === selector) || cssRules[sheet.insertRule(`${selector}{}`, 0)];
-    if (isCSSStyleRule(cssRule)) {
-      const { style: style2 } = cssRule;
-      value = `${value}`;
-      if (style2[prop] !== value) {
-        style2[prop] = value;
-      }
-    }
-  }
-  function ruleBy(target, prop, value) {
-    rule(`#${isHTMLElement(target) ? target.id : target}`, prop, value);
-  }
-  function isCSSStyleRule(cssRule) {
-    return cssRule instanceof CSSStyleRule;
-  }
-  return {
-    mount,
-    destroy,
-    rule,
-    ruleBy
-  };
-}
-
 const ROLE = "role";
 const ARIA_CONTROLS = "aria-controls";
 const ARIA_CURRENT = "aria-current";
@@ -798,6 +767,7 @@ function Slide$1(Splide2, index, slideIndex, slide) {
   const { Components, root, options } = Splide2;
   const { isNavigation, updateOnMove } = options;
   const { resolve } = Components.Direction;
+  const styles = getAttribute(slide, "style");
   const isClone = slideIndex > -1;
   const container = child(slide, `.${CLASS_CONTAINER}`);
   const focusableNodes = options.focusableNodes && queryAll(slide, options.focusableNodes);
@@ -830,6 +800,7 @@ function Slide$1(Splide2, index, slideIndex, slide) {
     destroyEvents();
     removeClass(slide, STATUS_CLASSES);
     removeAttribute(slide, ALL_ATTRIBUTES);
+    setAttribute(slide, "style", styles);
   }
   function onMove(next, prev, dest) {
     if (!destroyed) {
@@ -871,9 +842,8 @@ function Slide$1(Splide2, index, slideIndex, slide) {
       emit(visible ? EVENT_VISIBLE : EVENT_HIDDEN, this);
     }
   }
-  function rule(prop, value, useContainer) {
-    const selector = `#${slide.id}${container && useContainer ? ` > .${CLASS_CONTAINER}` : ""}`;
-    Components.Style.rule(selector, prop, value);
+  function style$1(prop, value, useContainer) {
+    style(useContainer && container || slide, prop, value);
   }
   function isActive() {
     return Splide2.index === index;
@@ -903,7 +873,7 @@ function Slide$1(Splide2, index, slideIndex, slide) {
     isClone,
     mount,
     destroy,
-    rule,
+    style: style$1,
     isWithin
   };
 }
@@ -915,6 +885,9 @@ function Slides(Splide2, Components2, options) {
   function mount() {
     init();
     on(EVENT_REFRESH, refresh);
+    on([EVENT_MOUNTED, EVENT_REFRESH], () => {
+      Slides2.sort((Slide1, Slide2) => Slide1.index - Slide2.index);
+    });
   }
   function init() {
     slides.forEach((slide, index) => {
@@ -972,9 +945,9 @@ function Slides(Splide2, Components2, options) {
   function filter(matcher) {
     return Slides2.filter(isFunction(matcher) ? matcher : (Slide2) => isString(matcher) ? matches(Slide2.slide, matcher) : includes(toArray(matcher), Slide2.index));
   }
-  function rule(prop, value, useContainer) {
+  function style(prop, value, useContainer) {
     forEach$1((Slide2) => {
-      Slide2.rule(prop, value, useContainer);
+      Slide2.style(prop, value, useContainer);
     });
   }
   function observeImages(elm, callback) {
@@ -1009,85 +982,15 @@ function Slides(Splide2, Components2, options) {
     remove: remove$1,
     forEach: forEach$1,
     filter,
-    rule,
+    style,
     getLength,
     isEnough
   };
 }
 
-function Clones(Splide2, Components2, options) {
-  const { on, emit } = EventInterface(Splide2);
-  const { Elements, Slides } = Components2;
-  const { resolve } = Components2.Direction;
-  const clones = [];
-  let cloneCount;
-  function mount() {
-    init();
-    on(EVENT_REFRESH, refresh);
-    on([EVENT_UPDATED, EVENT_RESIZE], observe);
-  }
-  function init() {
-    if (cloneCount = computeCloneCount()) {
-      generate(cloneCount);
-    }
-  }
-  function destroy() {
-    remove(clones);
-    empty(clones);
-  }
-  function refresh() {
-    destroy();
-    init();
-  }
-  function observe() {
-    if (cloneCount !== computeCloneCount()) {
-      emit(EVENT_REFRESH);
-    }
-  }
-  function generate(count) {
-    const slides = Slides.get().slice();
-    const { length } = slides;
-    if (length) {
-      while (slides.length < count) {
-        push(slides, slides);
-      }
-      push(slides.slice(-count), slides.slice(0, count)).forEach((Slide, index) => {
-        const isHead = index < count;
-        const clone = cloneDeep(Slide.slide, index);
-        isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);
-        push(clones, clone);
-        Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);
-      });
-    }
-  }
-  function cloneDeep(elm, index) {
-    const clone = elm.cloneNode(true);
-    addClass(clone, options.classes.clone);
-    clone.id = `${Splide2.root.id}-clone${pad(index + 1)}`;
-    return clone;
-  }
-  function computeCloneCount() {
-    let { clones: clones2 } = options;
-    if (!Splide2.is(LOOP)) {
-      clones2 = 0;
-    } else if (!clones2) {
-      const fixedSize = measure(Elements.list, options[resolve("fixedWidth")]);
-      const fixedCount = fixedSize && ceil(rect(Elements.track)[resolve("width")] / fixedSize);
-      const baseCount = fixedCount || options[resolve("autoWidth")] && Splide2.length || options.perPage;
-      clones2 = baseCount * (options.drag ? (options.flickMaxPages || 1) + 1 : 2);
-    }
-    return clones2;
-  }
-  return {
-    mount,
-    destroy
-  };
-}
-
 function Layout(Splide2, Components2, options) {
   const { on, bind, emit } = EventInterface(Splide2);
   const { Slides } = Components2;
-  const { ruleBy } = Components2.Style;
   const { resolve } = Components2.Direction;
   const { track, list } = Components2.Elements;
   const { getAt } = Slides;
@@ -1100,21 +1003,20 @@ function Layout(Splide2, Components2, options) {
   }
   function init() {
     vertical = options.direction === TTB;
-    ruleBy(Splide2.root, "maxWidth", unit(options.width));
-    ruleBy(track, resolve("paddingLeft"), cssPadding(false));
-    ruleBy(track, resolve("paddingRight"), cssPadding(true));
-    Slides.rule(resolve("marginRight"), unit(options.gap));
-    Slides.rule("width", cssSlideWidth());
-    setSlidesHeight();
+    style(Splide2.root, "maxWidth", unit(options.width));
+    style(track, resolve("paddingLeft"), cssPadding(false));
+    style(track, resolve("paddingRight"), cssPadding(true));
     resize();
   }
   function resize() {
-    ruleBy(track, "height", cssTrackHeight());
-    options.heightRatio && setSlidesHeight();
+    style(track, "height", cssTrackHeight());
+    Slides.style(resolve("marginRight"), unit(options.gap));
+    Slides.style("width", cssSlideWidth() || null);
+    setSlidesHeight();
     emit(EVENT_RESIZED);
   }
   function setSlidesHeight() {
-    Slides.rule("height", cssSlideHeight(), true);
+    Slides.style("height", cssSlideHeight(), true);
   }
   function cssPadding(right) {
     const { padding } = options;
@@ -1179,6 +1081,76 @@ function Layout(Splide2, Components2, options) {
   };
 }
 
+function Clones(Splide2, Components2, options) {
+  const { on, emit } = EventInterface(Splide2);
+  const { Elements, Slides } = Components2;
+  const { resolve } = Components2.Direction;
+  const clones = [];
+  let cloneCount;
+  function mount() {
+    init();
+    on(EVENT_REFRESH, refresh);
+    on([EVENT_UPDATED, EVENT_RESIZE], observe);
+  }
+  function init() {
+    if (cloneCount = computeCloneCount()) {
+      generate(cloneCount);
+      emit(EVENT_RESIZE);
+    }
+  }
+  function destroy() {
+    remove(clones);
+    empty(clones);
+  }
+  function refresh() {
+    destroy();
+    init();
+  }
+  function observe() {
+    if (cloneCount < computeCloneCount()) {
+      emit(EVENT_REFRESH);
+    }
+  }
+  function generate(count) {
+    const slides = Slides.get().slice();
+    const { length } = slides;
+    if (length) {
+      while (slides.length < count) {
+        push(slides, slides);
+      }
+      push(slides.slice(-count), slides.slice(0, count)).forEach((Slide, index) => {
+        const isHead = index < count;
+        const clone = cloneDeep(Slide.slide, index);
+        isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);
+        push(clones, clone);
+        Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);
+      });
+    }
+  }
+  function cloneDeep(elm, index) {
+    const clone = elm.cloneNode(true);
+    addClass(clone, options.classes.clone);
+    clone.id = `${Splide2.root.id}-clone${pad(index + 1)}`;
+    return clone;
+  }
+  function computeCloneCount() {
+    let { clones: clones2 } = options;
+    if (!Splide2.is(LOOP)) {
+      clones2 = 0;
+    } else if (!clones2) {
+      const fixedSize = measure(Elements.list, options[resolve("fixedWidth")]);
+      const fixedCount = fixedSize && ceil(rect(Elements.track)[resolve("width")] / fixedSize);
+      const baseCount = fixedCount || options[resolve("autoWidth")] && Splide2.length || options.perPage;
+      clones2 = baseCount * (options.drag ? (options.flickMaxPages || 1) + 1 : 2);
+    }
+    return clones2;
+  }
+  return {
+    mount,
+    destroy
+  };
+}
+
 function Move(Splide2, Components2, options) {
   const { on, emit } = EventInterface(Splide2);
   const { slideSize, getPadding, totalSize, listSize, sliderSize } = Components2.Layout;
@@ -1231,13 +1203,17 @@ function Move(Splide2, Components2, options) {
       const exceededMin = exceededLimit(false, position) && diff < 0;
       const exceededMax = exceededLimit(true, position) && diff > 0;
       if (exceededMin || exceededMax) {
-        const excess = position - getLimit(exceededMax);
-        const size = sliderSize();
-        position -= sign(excess) * size * ceil(abs(excess) / size);
+        position = shift(position, exceededMax);
       }
     }
     return position;
   }
+  function shift(position, backwards) {
+    const excess = position - getLimit(backwards);
+    const size = sliderSize();
+    position -= sign(excess) * size * ceil(abs(excess) / size);
+    return position;
+  }
   function cancel() {
     waiting = false;
     translate(getPosition());
@@ -1295,6 +1271,7 @@ function Move(Splide2, Components2, options) {
     move,
     jump,
     translate,
+    shift,
     cancel,
     toIndex,
     toPosition,
@@ -1311,6 +1288,7 @@ function Controller(Splide2, Components2, options) {
   const { getPosition, getLimit } = Move;
   const { isEnough, getLength } = Components2.Slides;
   const isLoop = Splide2.is(LOOP);
+  const isSlide = Splide2.is(SLIDE);
   let currIndex = options.start || 0;
   let prevIndex = currIndex;
   let slideCount;
@@ -1319,7 +1297,6 @@ function Controller(Splide2, Components2, options) {
   function mount() {
     init();
     on([EVENT_UPDATED, EVENT_REFRESH], init, DEFAULT_EVENT_PRIORITY - 1);
-    on(EVENT_SCROLLED, reindex, 0);
   }
   function init() {
     slideCount = getLength(true);
@@ -1327,17 +1304,25 @@ function Controller(Splide2, Components2, options) {
     perPage = options.perPage;
     currIndex = clamp(currIndex, 0, slideCount - 1);
   }
-  function reindex() {
-    setIndex(Move.toIndex(getPosition()));
-  }
   function go(control, allowSameIndex, callback) {
     const dest = parse(control);
-    const index = loop(dest);
-    if (index > -1 && !Move.isBusy() && (allowSameIndex || index !== currIndex)) {
-      setIndex(index);
-      Move.move(dest, index, prevIndex, callback);
+    if (options.useScroll) {
+      scroll(dest, true, true, options.speed, callback);
+    } else {
+      const index = loop(dest);
+      if (index > -1 && !Move.isBusy() && (allowSameIndex || index !== currIndex)) {
+        setIndex(index);
+        Move.move(dest, index, prevIndex, callback);
+      }
     }
   }
+  function scroll(destination, useIndex, snap, duration, callback) {
+    const dest = useIndex ? destination : toDest(destination);
+    Components2.Scroll.scroll(useIndex || snap ? Move.toPosition(dest, true) : destination, duration, () => {
+      setIndex(Move.toIndex(Move.getPosition()));
+      callback && callback();
+    });
+  }
   function parse(control) {
     let index = currIndex;
     if (isString(control)) {
@@ -1367,7 +1352,7 @@ function Controller(Splide2, Components2, options) {
   function getAdjacent(prev, destination) {
     const number = perMove || hasFocus() ? 1 : perPage;
     const dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex);
-    if (dest === -1 && Splide2.is(SLIDE)) {
+    if (dest === -1 && isSlide) {
       if (!approximatelyEqual(getPosition(), getLimit(!prev), 1)) {
         return prev ? 0 : getEnd();
       }
@@ -1422,6 +1407,10 @@ function Controller(Splide2, Components2, options) {
     }
     return index;
   }
+  function toDest(destination) {
+    const closest = Move.toIndex(destination);
+    return isSlide ? clamp(closest, 0, getEnd()) : closest;
+  }
   function setIndex(index) {
     if (index !== currIndex) {
       prevIndex = currIndex;
@@ -1437,6 +1426,7 @@ function Controller(Splide2, Components2, options) {
   return {
     mount,
     go,
+    scroll,
     getNext,
     getPrev,
     getEnd,
@@ -1444,6 +1434,7 @@ function Controller(Splide2, Components2, options) {
     getIndex,
     toIndex,
     toPage,
+    toDest,
     hasFocus
   };
 }
@@ -1604,7 +1595,7 @@ function Autoplay(Splide2, Components2, options) {
   function update(rate) {
     const { bar } = Elements;
     if (bar) {
-      style(bar, { width: `${rate * 100}%` });
+      style(bar, "width", `${rate * 100}%`);
     }
     emit(EVENT_AUTOPLAY_PLAYING, rate);
   }
@@ -1639,7 +1630,7 @@ function Cover(Splide2, Components2, options) {
     });
   }
   function toggle(cover, img, Slide) {
-    Slide.rule("background", cover ? `center/cover no-repeat url("${img.src}")` : "", true);
+    Slide.style("background", cover ? `center/cover no-repeat url("${img.src}")` : "", true);
     display(img, cover ? "none" : "");
   }
   return {
@@ -1659,14 +1650,16 @@ function Scroll(Splide2, Components2, options) {
   const { Move } = Components2;
   const { getPosition, getLimit, exceededLimit } = Move;
   let interval;
+  let scrollCallback;
   function mount() {
     on(EVENT_MOVE, clear);
     on([EVENT_UPDATED, EVENT_REFRESH], cancel);
   }
-  function scroll(destination, duration, suppressConstraint) {
+  function scroll(destination, duration, callback, suppressConstraint) {
     const start = getPosition();
     let friction = 1;
     duration = duration || computeDuration(abs(destination - start));
+    scrollCallback = callback;
     clear();
     interval = RequestInterval(duration, onScrolled, (rate) => {
       const position = getPosition();
@@ -1684,9 +1677,15 @@ function Scroll(Splide2, Components2, options) {
     interval.start();
   }
   function bounce(backwards) {
-    scroll(getLimit(!backwards), BOUNCE_DURATION, true);
+    scroll(getLimit(!backwards), BOUNCE_DURATION, null, true);
   }
   function onScrolled() {
+    const position = getPosition();
+    const index = Move.toIndex(position);
+    if (!between(index, 0, Splide2.length - 1)) {
+      Move.translate(Move.shift(position, index > 0), true);
+    }
+    scrollCallback && scrollCallback();
     emit(EVENT_SCROLLED);
   }
   function computeDuration(distance) {
@@ -1728,7 +1727,6 @@ function Drag(Splide2, Components2, options) {
   const { resolve, orient } = Components2.Direction;
   const { getPosition, exceededLimit } = Move;
   const listenerOptions = { passive: false, capture: true };
-  const isSlide = Splide2.is(SLIDE);
   let basePosition;
   let baseEvent;
   let prevBaseEvent;
@@ -1744,6 +1742,7 @@ function Drag(Splide2, Components2, options) {
     bind(track, POINTER_UP_EVENTS, noop, listenerOptions);
     bind(track, POINTER_DOWN_EVENTS, onPointerDown, listenerOptions);
     bind(track, "click", onClick, { capture: true });
+    bind(track, "dragstart", prevent);
     on([EVENT_MOUNTED, EVENT_UPDATED], init);
   }
   function init() {
@@ -1804,11 +1803,11 @@ function Drag(Splide2, Components2, options) {
         const velocity = computeVelocity(e);
         const destination = computeDestination(velocity);
         if (isFree) {
-          Scroll.scroll(destination);
+          Controller.scroll(destination);
         } else if (Splide2.is(FADE)) {
           Controller.go(Splide2.index + orient(sign(velocity)));
         } else {
-          Controller.go(computeIndex(destination), true);
+          Controller.go(Controller.toDest(destination), true);
         }
         prevent(e);
       }
@@ -1846,10 +1845,6 @@ function Drag(Splide2, Components2, options) {
   function computeDestination(velocity) {
     return getPosition() + sign(velocity) * min(abs(velocity) * (options.flickPower || 600), isFree ? Infinity : Components2.Layout.listSize() * (options.flickMaxPages || 1));
   }
-  function computeIndex(destination) {
-    const dest = Move.toIndex(destination);
-    return isSlide ? clamp(dest, 0, Controller.getEnd()) : dest;
-  }
   function coordOf(e, orthogonal) {
     return (isTouchEvent(e) ? e.touches[0] : e)[`page${resolve(orthogonal ? "Y" : "X")}`];
   }
@@ -1860,7 +1855,7 @@ function Drag(Splide2, Components2, options) {
     return e.timeStamp;
   }
   function constrain(diff) {
-    return diff / (hasExceeded && isSlide ? FRICTION : 1);
+    return diff / (hasExceeded && Splide2.is(SLIDE) ? FRICTION : 1);
   }
   function disable(value) {
     disabled = value;
@@ -2160,10 +2155,9 @@ var ComponentConstructors = /*#__PURE__*/Object.freeze({
   Options: Options,
   Direction: Direction,
   Elements: Elements,
-  Style: Style$1,
   Slides: Slides,
-  Clones: Clones,
   Layout: Layout,
+  Clones: Clones,
   Move: Move,
   Controller: Controller,
   Arrows: Arrows,
@@ -2200,7 +2194,7 @@ const DEFAULTS = {
   pauseOnHover: true,
   pauseOnFocus: true,
   resetProgress: true,
-  easing: "cubic-bezier(.42,.65,.27,.99)",
+  easing: "cubic-bezier(0.25, 1, 0.5, 1)",
   drag: true,
   direction: "ltr",
   slideFocus: true,
@@ -2212,22 +2206,19 @@ const DEFAULTS = {
 
 function Fade(Splide2, Components2, options) {
   const { on } = EventInterface(Splide2);
-  const { ruleBy } = Components2.Style;
   function mount() {
     on([EVENT_MOUNTED, EVENT_REFRESH], () => {
       nextTick(() => {
-        Components2.Slides.forEach((Slide) => {
-          ruleBy(Slide.slide, "transition", `opacity ${options.speed}ms ${options.easing}`);
-        });
+        Components2.Slides.style("transition", `opacity ${options.speed}ms ${options.easing}`);
       });
     });
   }
   function start(index, done) {
     const { track } = Components2.Elements;
-    ruleBy(track, "height", unit(rect(track).height));
+    style(track, "height", unit(rect(track).height));
     nextTick(() => {
       done();
-      ruleBy(track, "height", "");
+      style(track, "height", "");
     });
   }
   return {
@@ -2278,7 +2269,7 @@ function Slide(Splide2, Components2, options) {
     return options.speed;
   }
   function apply(transition) {
-    Components2.Style.ruleBy(list, "transition", transition);
+    style(list, "transition", transition);
   }
   return {
     mount,

+ 184 - 202
dist/js/splide.js

@@ -4,7 +4,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
 /*!
  * Splide.js
- * Version  : 3.0.9
+ * Version  : 3.1.0
  * License  : MIT
  * Copyright: 2021 Naotoshi Fujita
  */
@@ -200,22 +200,23 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     return elm;
   }
 
-  function style(elm, styles) {
-    if (isString(styles)) {
-      return getComputedStyle(elm)[styles];
+  function style(elm, prop, value) {
+    if (isUndefined(value)) {
+      return getComputedStyle(elm)[prop];
     }
 
-    forOwn(styles, function (value, key) {
-      if (!isNull(value)) {
-        elm.style[key] = "" + value;
+    if (!isNull(value)) {
+      var style2 = elm.style;
+      value = "" + value;
+
+      if (style2[prop] !== value) {
+        style2[prop] = value;
       }
-    });
+    }
   }
 
   function display(elm, display2) {
-    style(elm, {
-      display: display2
-    });
+    style(elm, "display", display2);
   }
 
   function getAttribute(elm, attr) {
@@ -776,6 +777,9 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function destroy() {
+      [root, track, list].forEach(function (elm) {
+        removeAttribute(elm, "style");
+      });
       empty(slides);
       removeClass(root, classes);
     }
@@ -836,53 +840,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     });
   }
 
-  function Style() {
-    var style;
-    var sheet;
-
-    function mount() {
-      style = create("style", {}, document.head);
-      sheet = style.sheet;
-    }
-
-    function destroy() {
-      remove(style);
-      sheet = null;
-    }
-
-    function rule(selector, prop, value) {
-      var _sheet = sheet,
-          cssRules = _sheet.cssRules;
-      var cssRule = find(cssRules, function (cssRule2) {
-        return isCSSStyleRule(cssRule2) && cssRule2.selectorText === selector;
-      }) || cssRules[sheet.insertRule(selector + "{}", 0)];
-
-      if (isCSSStyleRule(cssRule)) {
-        var style2 = cssRule.style;
-        value = "" + value;
-
-        if (style2[prop] !== value) {
-          style2[prop] = value;
-        }
-      }
-    }
-
-    function ruleBy(target, prop, value) {
-      rule("#" + (isHTMLElement(target) ? target.id : target), prop, value);
-    }
-
-    function isCSSStyleRule(cssRule) {
-      return cssRule instanceof CSSStyleRule;
-    }
-
-    return {
-      mount: mount,
-      destroy: destroy,
-      rule: rule,
-      ruleBy: ruleBy
-    };
-  }
-
   var ROLE = "role";
   var ARIA_CONTROLS = "aria-controls";
   var ARIA_CURRENT = "aria-current";
@@ -909,6 +866,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     var isNavigation = options.isNavigation,
         updateOnMove = options.updateOnMove;
     var resolve = Components.Direction.resolve;
+    var styles = getAttribute(slide, "style");
     var isClone = slideIndex > -1;
     var container = child(slide, "." + CLASS_CONTAINER);
     var focusableNodes = options.focusableNodes && queryAll(slide, options.focusableNodes);
@@ -950,6 +908,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       destroyEvents();
       removeClass(slide, STATUS_CLASSES);
       removeAttribute(slide, ALL_ATTRIBUTES);
+      setAttribute(slide, "style", styles);
     }
 
     function onMove(next, prev, dest) {
@@ -1001,9 +960,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       }
     }
 
-    function rule(prop, value, useContainer) {
-      var selector = "#" + slide.id + (container && useContainer ? " > ." + CLASS_CONTAINER : "");
-      Components.Style.rule(selector, prop, value);
+    function style$1(prop, value, useContainer) {
+      style(useContainer && container || slide, prop, value);
     }
 
     function isActive() {
@@ -1040,7 +998,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       isClone: isClone,
       mount: mount,
       destroy: destroy,
-      rule: rule,
+      style: style$1,
       isWithin: isWithin
     };
   }
@@ -1059,6 +1017,11 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function mount() {
       init();
       on(EVENT_REFRESH, refresh);
+      on([EVENT_MOUNTED, EVENT_REFRESH], function () {
+        Slides2.sort(function (Slide1, Slide2) {
+          return Slide1.index - Slide2.index;
+        });
+      });
     }
 
     function init() {
@@ -1137,9 +1100,9 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       });
     }
 
-    function rule(prop, value, useContainer) {
+    function style(prop, value, useContainer) {
       forEach$1(function (Slide2) {
-        Slide2.rule(prop, value, useContainer);
+        Slide2.style(prop, value, useContainer);
       });
     }
 
@@ -1179,106 +1142,19 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       remove: remove$1,
       forEach: forEach$1,
       filter: filter,
-      rule: rule,
+      style: style,
       getLength: getLength,
       isEnough: isEnough
     };
   }
 
-  function Clones(Splide2, Components2, options) {
+  function Layout(Splide2, Components2, options) {
     var _EventInterface4 = EventInterface(Splide2),
         on = _EventInterface4.on,
+        bind = _EventInterface4.bind,
         emit = _EventInterface4.emit;
 
-    var Elements = Components2.Elements,
-        Slides = Components2.Slides;
-    var resolve = Components2.Direction.resolve;
-    var clones = [];
-    var cloneCount;
-
-    function mount() {
-      init();
-      on(EVENT_REFRESH, refresh);
-      on([EVENT_UPDATED, EVENT_RESIZE], observe);
-    }
-
-    function init() {
-      if (cloneCount = computeCloneCount()) {
-        generate(cloneCount);
-      }
-    }
-
-    function destroy() {
-      remove(clones);
-      empty(clones);
-    }
-
-    function refresh() {
-      destroy();
-      init();
-    }
-
-    function observe() {
-      if (cloneCount !== computeCloneCount()) {
-        emit(EVENT_REFRESH);
-      }
-    }
-
-    function generate(count) {
-      var slides = Slides.get().slice();
-      var length = slides.length;
-
-      if (length) {
-        while (slides.length < count) {
-          push(slides, slides);
-        }
-
-        push(slides.slice(-count), slides.slice(0, count)).forEach(function (Slide, index) {
-          var isHead = index < count;
-          var clone = cloneDeep(Slide.slide, index);
-          isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);
-          push(clones, clone);
-          Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);
-        });
-      }
-    }
-
-    function cloneDeep(elm, index) {
-      var clone = elm.cloneNode(true);
-      addClass(clone, options.classes.clone);
-      clone.id = Splide2.root.id + "-clone" + pad(index + 1);
-      return clone;
-    }
-
-    function computeCloneCount() {
-      var clones2 = options.clones;
-
-      if (!Splide2.is(LOOP)) {
-        clones2 = 0;
-      } else if (!clones2) {
-        var fixedSize = measure(Elements.list, options[resolve("fixedWidth")]);
-        var fixedCount = fixedSize && ceil(rect(Elements.track)[resolve("width")] / fixedSize);
-        var baseCount = fixedCount || options[resolve("autoWidth")] && Splide2.length || options.perPage;
-        clones2 = baseCount * (options.drag ? (options.flickMaxPages || 1) + 1 : 2);
-      }
-
-      return clones2;
-    }
-
-    return {
-      mount: mount,
-      destroy: destroy
-    };
-  }
-
-  function Layout(Splide2, Components2, options) {
-    var _EventInterface5 = EventInterface(Splide2),
-        on = _EventInterface5.on,
-        bind = _EventInterface5.bind,
-        emit = _EventInterface5.emit;
-
     var Slides = Components2.Slides;
-    var ruleBy = Components2.Style.ruleBy;
     var resolve = Components2.Direction.resolve;
     var _Components2$Elements2 = Components2.Elements,
         track = _Components2$Elements2.track,
@@ -1295,23 +1171,22 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
 
     function init() {
       vertical = options.direction === TTB;
-      ruleBy(Splide2.root, "maxWidth", unit(options.width));
-      ruleBy(track, resolve("paddingLeft"), cssPadding(false));
-      ruleBy(track, resolve("paddingRight"), cssPadding(true));
-      Slides.rule(resolve("marginRight"), unit(options.gap));
-      Slides.rule("width", cssSlideWidth());
-      setSlidesHeight();
+      style(Splide2.root, "maxWidth", unit(options.width));
+      style(track, resolve("paddingLeft"), cssPadding(false));
+      style(track, resolve("paddingRight"), cssPadding(true));
       resize();
     }
 
     function resize() {
-      ruleBy(track, "height", cssTrackHeight());
-      options.heightRatio && setSlidesHeight();
+      style(track, "height", cssTrackHeight());
+      Slides.style(resolve("marginRight"), unit(options.gap));
+      Slides.style("width", cssSlideWidth() || null);
+      setSlidesHeight();
       emit(EVENT_RESIZED);
     }
 
     function setSlidesHeight() {
-      Slides.rule("height", cssSlideHeight(), true);
+      Slides.style("height", cssSlideHeight(), true);
     }
 
     function cssPadding(right) {
@@ -1393,6 +1268,93 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     };
   }
 
+  function Clones(Splide2, Components2, options) {
+    var _EventInterface5 = EventInterface(Splide2),
+        on = _EventInterface5.on,
+        emit = _EventInterface5.emit;
+
+    var Elements = Components2.Elements,
+        Slides = Components2.Slides;
+    var resolve = Components2.Direction.resolve;
+    var clones = [];
+    var cloneCount;
+
+    function mount() {
+      init();
+      on(EVENT_REFRESH, refresh);
+      on([EVENT_UPDATED, EVENT_RESIZE], observe);
+    }
+
+    function init() {
+      if (cloneCount = computeCloneCount()) {
+        generate(cloneCount);
+        emit(EVENT_RESIZE);
+      }
+    }
+
+    function destroy() {
+      remove(clones);
+      empty(clones);
+    }
+
+    function refresh() {
+      destroy();
+      init();
+    }
+
+    function observe() {
+      if (cloneCount < computeCloneCount()) {
+        emit(EVENT_REFRESH);
+      }
+    }
+
+    function generate(count) {
+      var slides = Slides.get().slice();
+      var length = slides.length;
+
+      if (length) {
+        while (slides.length < count) {
+          push(slides, slides);
+        }
+
+        push(slides.slice(-count), slides.slice(0, count)).forEach(function (Slide, index) {
+          var isHead = index < count;
+          var clone = cloneDeep(Slide.slide, index);
+          isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);
+          push(clones, clone);
+          Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);
+        });
+      }
+    }
+
+    function cloneDeep(elm, index) {
+      var clone = elm.cloneNode(true);
+      addClass(clone, options.classes.clone);
+      clone.id = Splide2.root.id + "-clone" + pad(index + 1);
+      return clone;
+    }
+
+    function computeCloneCount() {
+      var clones2 = options.clones;
+
+      if (!Splide2.is(LOOP)) {
+        clones2 = 0;
+      } else if (!clones2) {
+        var fixedSize = measure(Elements.list, options[resolve("fixedWidth")]);
+        var fixedCount = fixedSize && ceil(rect(Elements.track)[resolve("width")] / fixedSize);
+        var baseCount = fixedCount || options[resolve("autoWidth")] && Splide2.length || options.perPage;
+        clones2 = baseCount * (options.drag ? (options.flickMaxPages || 1) + 1 : 2);
+      }
+
+      return clones2;
+    }
+
+    return {
+      mount: mount,
+      destroy: destroy
+    };
+  }
+
   function Move(Splide2, Components2, options) {
     var _EventInterface6 = EventInterface(Splide2),
         on = _EventInterface6.on,
@@ -1466,15 +1428,20 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         var exceededMax = exceededLimit(true, position) && diff > 0;
 
         if (exceededMin || exceededMax) {
-          var excess = position - getLimit(exceededMax);
-          var size = sliderSize();
-          position -= sign(excess) * size * ceil(abs(excess) / size);
+          position = shift(position, exceededMax);
         }
       }
 
       return position;
     }
 
+    function shift(position, backwards) {
+      var excess = position - getLimit(backwards);
+      var size = sliderSize();
+      position -= sign(excess) * size * ceil(abs(excess) / size);
+      return position;
+    }
+
     function cancel() {
       waiting = false;
       translate(getPosition());
@@ -1545,6 +1512,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       move: move,
       jump: jump,
       translate: translate,
+      shift: shift,
       cancel: cancel,
       toIndex: toIndex,
       toPosition: toPosition,
@@ -1566,6 +1534,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         isEnough = _Components2$Slides.isEnough,
         getLength = _Components2$Slides.getLength;
     var isLoop = Splide2.is(LOOP);
+    var isSlide = Splide2.is(SLIDE);
     var currIndex = options.start || 0;
     var prevIndex = currIndex;
     var slideCount;
@@ -1575,7 +1544,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     function mount() {
       init();
       on([EVENT_UPDATED, EVENT_REFRESH], init, DEFAULT_EVENT_PRIORITY - 1);
-      on(EVENT_SCROLLED, reindex, 0);
     }
 
     function init() {
@@ -1585,20 +1553,29 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       currIndex = clamp(currIndex, 0, slideCount - 1);
     }
 
-    function reindex() {
-      setIndex(Move.toIndex(getPosition()));
-    }
-
     function go(control, allowSameIndex, callback) {
       var dest = parse(control);
-      var index = loop(dest);
 
-      if (index > -1 && !Move.isBusy() && (allowSameIndex || index !== currIndex)) {
-        setIndex(index);
-        Move.move(dest, index, prevIndex, callback);
+      if (options.useScroll) {
+        scroll(dest, true, true, options.speed, callback);
+      } else {
+        var index = loop(dest);
+
+        if (index > -1 && !Move.isBusy() && (allowSameIndex || index !== currIndex)) {
+          setIndex(index);
+          Move.move(dest, index, prevIndex, callback);
+        }
       }
     }
 
+    function scroll(destination, useIndex, snap, duration, callback) {
+      var dest = useIndex ? destination : toDest(destination);
+      Components2.Scroll.scroll(useIndex || snap ? Move.toPosition(dest, true) : destination, duration, function () {
+        setIndex(Move.toIndex(Move.getPosition()));
+        callback && callback();
+      });
+    }
+
     function parse(control) {
       var index = currIndex;
 
@@ -1637,7 +1614,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       var number = perMove || hasFocus() ? 1 : perPage;
       var dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex);
 
-      if (dest === -1 && Splide2.is(SLIDE)) {
+      if (dest === -1 && isSlide) {
         if (!approximatelyEqual(getPosition(), getLimit(!prev), 1)) {
           return prev ? 0 : getEnd();
         }
@@ -1705,6 +1682,11 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       return index;
     }
 
+    function toDest(destination) {
+      var closest = Move.toIndex(destination);
+      return isSlide ? clamp(closest, 0, getEnd()) : closest;
+    }
+
     function setIndex(index) {
       if (index !== currIndex) {
         prevIndex = currIndex;
@@ -1723,6 +1705,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     return {
       mount: mount,
       go: go,
+      scroll: scroll,
       getNext: getNext,
       getPrev: getPrev,
       getEnd: getEnd,
@@ -1730,6 +1713,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       getIndex: getIndex,
       toIndex: toIndex,
       toPage: toPage,
+      toDest: toDest,
       hasFocus: hasFocus
     };
   }
@@ -1928,9 +1912,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       var bar = Elements.bar;
 
       if (bar) {
-        style(bar, {
-          width: rate * 100 + "%"
-        });
+        style(bar, "width", rate * 100 + "%");
       }
 
       emit(EVENT_AUTOPLAY_PLAYING, rate);
@@ -1973,7 +1955,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function toggle(cover, img, Slide) {
-      Slide.rule("background", cover ? "center/cover no-repeat url(\"" + img.src + "\")" : "", true);
+      Slide.style("background", cover ? "center/cover no-repeat url(\"" + img.src + "\")" : "", true);
       display(img, cover ? "none" : "");
     }
 
@@ -1999,16 +1981,18 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
         getLimit = Move.getLimit,
         exceededLimit = Move.exceededLimit;
     var interval;
+    var scrollCallback;
 
     function mount() {
       on(EVENT_MOVE, clear);
       on([EVENT_UPDATED, EVENT_REFRESH], cancel);
     }
 
-    function scroll(destination, duration, suppressConstraint) {
+    function scroll(destination, duration, callback, suppressConstraint) {
       var start = getPosition();
       var friction = 1;
       duration = duration || computeDuration(abs(destination - start));
+      scrollCallback = callback;
       clear();
       interval = RequestInterval(duration, onScrolled, function (rate) {
         var position = getPosition();
@@ -2029,10 +2013,18 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function bounce(backwards) {
-      scroll(getLimit(!backwards), BOUNCE_DURATION, true);
+      scroll(getLimit(!backwards), BOUNCE_DURATION, null, true);
     }
 
     function onScrolled() {
+      var position = getPosition();
+      var index = Move.toIndex(position);
+
+      if (!between(index, 0, Splide2.length - 1)) {
+        Move.translate(Move.shift(position, index > 0), true);
+      }
+
+      scrollCallback && scrollCallback();
       emit(EVENT_SCROLLED);
     }
 
@@ -2092,7 +2084,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       passive: false,
       capture: true
     };
-    var isSlide = Splide2.is(SLIDE);
     var basePosition;
     var baseEvent;
     var prevBaseEvent;
@@ -2111,6 +2102,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       bind(track, "click", onClick, {
         capture: true
       });
+      bind(track, "dragstart", prevent);
       on([EVENT_MOUNTED, EVENT_UPDATED], init);
     }
 
@@ -2183,11 +2175,11 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
           var destination = computeDestination(velocity);
 
           if (isFree) {
-            Scroll.scroll(destination);
+            Controller.scroll(destination);
           } else if (Splide2.is(FADE)) {
             Controller.go(Splide2.index + orient(sign(velocity)));
           } else {
-            Controller.go(computeIndex(destination), true);
+            Controller.go(Controller.toDest(destination), true);
           }
 
           prevent(e);
@@ -2236,11 +2228,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
       return getPosition() + sign(velocity) * min(abs(velocity) * (options.flickPower || 600), isFree ? Infinity : Components2.Layout.listSize() * (options.flickMaxPages || 1));
     }
 
-    function computeIndex(destination) {
-      var dest = Move.toIndex(destination);
-      return isSlide ? clamp(dest, 0, Controller.getEnd()) : dest;
-    }
-
     function coordOf(e, orthogonal) {
       return (isTouchEvent(e) ? e.touches[0] : e)["page" + resolve(orthogonal ? "Y" : "X")];
     }
@@ -2254,7 +2241,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function constrain(diff) {
-      return diff / (hasExceeded && isSlide ? FRICTION : 1);
+      return diff / (hasExceeded && Splide2.is(SLIDE) ? FRICTION : 1);
     }
 
     function disable(value) {
@@ -2656,10 +2643,9 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     Options: Options,
     Direction: Direction,
     Elements: Elements,
-    Style: Style,
     Slides: Slides,
-    Clones: Clones,
     Layout: Layout,
+    Clones: Clones,
     Move: Move,
     Controller: Controller,
     Arrows: Arrows,
@@ -2694,7 +2680,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     pauseOnHover: true,
     pauseOnFocus: true,
     resetProgress: true,
-    easing: "cubic-bezier(.42,.65,.27,.99)",
+    easing: "cubic-bezier(0.25, 1, 0.5, 1)",
     drag: true,
     direction: "ltr",
     slideFocus: true,
@@ -2708,24 +2694,20 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     var _EventInterface18 = EventInterface(Splide2),
         on = _EventInterface18.on;
 
-    var ruleBy = Components2.Style.ruleBy;
-
     function mount() {
       on([EVENT_MOUNTED, EVENT_REFRESH], function () {
         nextTick(function () {
-          Components2.Slides.forEach(function (Slide) {
-            ruleBy(Slide.slide, "transition", "opacity " + options.speed + "ms " + options.easing);
-          });
+          Components2.Slides.style("transition", "opacity " + options.speed + "ms " + options.easing);
         });
       });
     }
 
     function start(index, done) {
       var track = Components2.Elements.track;
-      ruleBy(track, "height", unit(rect(track).height));
+      style(track, "height", unit(rect(track).height));
       nextTick(function () {
         done();
-        ruleBy(track, "height", "");
+        style(track, "height", "");
       });
     }
 
@@ -2789,7 +2771,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
     }
 
     function apply(transition) {
-      Components2.Style.ruleBy(list, "transition", transition);
+      style(list, "transition", transition);
     }
 
     return {

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


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


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


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

@@ -1 +1 @@
-{"version":3,"file":"Clones.d.ts","sourceRoot":"","sources":["Clones.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,cAAe,SAAQ,aAAa;CACpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,cAAc,CA4HjG"}
+{"version":3,"file":"Clones.d.ts","sourceRoot":"","sources":["Clones.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,cAAe,SAAQ,aAAa;CACpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,cAAc,CA6HjG"}

+ 2 - 0
dist/types/components/Controller/Controller.d.ts

@@ -7,6 +7,7 @@ import { AnyFunction, BaseComponent, Components, Options } from '../../types';
  */
 export interface ControllerComponent extends BaseComponent {
     go(control: number | string, allowSameIndex?: boolean, callback?: AnyFunction): void;
+    scroll(destination: number, useIndex?: boolean, snap?: boolean, duration?: number, callback?: AnyFunction): void;
     getNext(destination?: boolean): number;
     getPrev(destination?: boolean): number;
     getEnd(): number;
@@ -14,6 +15,7 @@ export interface ControllerComponent extends BaseComponent {
     getIndex(prev?: boolean): number;
     toIndex(page: number): number;
     toPage(index: number): number;
+    toDest(position: number): number;
     hasFocus(): boolean;
 }
 /**

+ 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,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,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,mBAAmB,CAoS1G"}
+{"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,CAwU1G"}

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

@@ -1 +1 @@
-{"version":3,"file":"Drag.d.ts","sourceRoot":"","sources":["Drag.ts"],"names":[],"mappings":"AAGA,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;IAClD,OAAO,CAAE,QAAQ,EAAE,OAAO,GAAI,IAAI,CAAA;CACnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,aAAa,CAkU9F"}
+{"version":3,"file":"Drag.d.ts","sourceRoot":"","sources":["Drag.ts"],"names":[],"mappings":"AAGA,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;IAClD,OAAO,CAAE,QAAQ,EAAE,OAAO,GAAI,IAAI,CAAA;CACnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,aAAa,CAsT9F"}

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

@@ -1 +1 @@
-{"version":3,"file":"Elements.d.ts","sourceRoot":"","sources":["Elements.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAIjE;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,WAAW,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa,EAAE,iBAAiB;CAC1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,iBAAiB,CA6ItG"}
+{"version":3,"file":"Elements.d.ts","sourceRoot":"","sources":["Elements.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAgBjE;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,WAAW,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa,EAAE,iBAAiB;CAC1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,iBAAiB,CAiJtG"}

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

@@ -1 +1 @@
-{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["Layout.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,eAAgB,SAAQ,aAAa;IACpD,QAAQ,IAAI,MAAM,CAAC;IACnB,SAAS,CAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACzD,UAAU,IAAI,MAAM,CAAC;IACrB,SAAS,CAAE,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IAC1D,UAAU,CAAE,KAAK,EAAE,OAAO,GAAI,MAAM,CAAC;CACtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,eAAe,CAmNlG"}
+{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["Layout.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,eAAgB,SAAQ,aAAa;IACpD,QAAQ,IAAI,MAAM,CAAC;IACnB,SAAS,CAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACzD,UAAU,IAAI,MAAM,CAAC;IACrB,SAAS,CAAE,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IAC1D,UAAU,CAAE,KAAK,EAAE,OAAO,GAAI,MAAM,CAAC;CACtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,eAAe,CAiNlG"}

+ 1 - 0
dist/types/components/Move/Move.d.ts

@@ -9,6 +9,7 @@ export interface MoveComponent extends BaseComponent {
     move(dest: number, index: number, prev: number, callback?: AnyFunction): void;
     jump(index: number): void;
     translate(position: number, preventLoop?: boolean): void;
+    shift(position: number, backwards: boolean): number;
     cancel(): void;
     toIndex(position: number): number;
     toPosition(index: number, trimming?: boolean): number;

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

@@ -1 +1 @@
-{"version":3,"file":"Move.d.ts","sourceRoot":"","sources":["Move.ts"],"names":[],"mappings":"AAYA,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,aAAc,SAAQ,aAAa;IAClD,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IAChF,IAAI,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI,CAAC;IAC5B,SAAS,CAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAI,IAAI,CAAC;IAC3D,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,CAAE,QAAQ,EAAE,MAAM,GAAI,MAAM,CAAC;IACpC,UAAU,CAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACxD,WAAW,IAAI,MAAM,CAAC;IACtB,QAAQ,CAAE,GAAG,EAAE,OAAO,GAAI,MAAM,CAAC;IACjC,MAAM,IAAI,OAAO,CAAC;IAClB,aAAa,CAAE,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAI,OAAO,CAAC;CACxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,aAAa,CAqP9F"}
+{"version":3,"file":"Move.d.ts","sourceRoot":"","sources":["Move.ts"],"names":[],"mappings":"AAYA,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,aAAc,SAAQ,aAAa;IAClD,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IAChF,IAAI,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI,CAAC;IAC5B,SAAS,CAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAI,IAAI,CAAC;IAC3D,KAAK,CAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAI,MAAM,CAAC;IACtD,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,CAAE,QAAQ,EAAE,MAAM,GAAI,MAAM,CAAC;IACpC,UAAU,CAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IACxD,WAAW,IAAI,MAAM,CAAC;IACtB,QAAQ,CAAE,GAAG,EAAE,OAAO,GAAI,MAAM,CAAC;IACjC,MAAM,IAAI,OAAO,CAAC;IAClB,aAAa,CAAE,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAI,OAAO,CAAC;CACxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,aAAa,CAmQ9F"}

+ 2 - 2
dist/types/components/Scroll/Scroll.d.ts

@@ -1,12 +1,12 @@
 import { Splide } from '../../core/Splide/Splide';
-import { BaseComponent, Components, Options } from '../../types';
+import { AnyFunction, BaseComponent, Components, Options } from '../../types';
 /**
  * The interface for the Scroll component.
  *
  * @since 3.0.0
  */
 export interface ScrollComponent extends BaseComponent {
-    scroll(position: number, duration?: number): void;
+    scroll(position: number, duration?: number, callback?: AnyFunction): void;
     cancel(): void;
 }
 /**

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

@@ -1 +1 @@
-{"version":3,"file":"Scroll.d.ts","sourceRoot":"","sources":["Scroll.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKjE;;;;GAIG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,MAAM,CAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAI,IAAI,CAAC;IACpD,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,eAAe,CAoHlG"}
+{"version":3,"file":"Scroll.d.ts","sourceRoot":"","sources":["Scroll.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAK9E;;;;GAIG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,MAAM,CAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAI,IAAI,CAAC;IAC5E,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,eAAe,CAqIlG"}

+ 2 - 2
dist/types/components/Slides/Slide.d.ts

@@ -11,7 +11,7 @@ export interface SlideComponent extends BaseComponent {
     slide: HTMLElement;
     container: HTMLElement;
     isClone: boolean;
-    rule(prop: string, value: string | number, useContainer?: boolean): void;
+    style(prop: string, value: string | number, useContainer?: boolean): void;
     isWithin(from: number, distance: number): boolean;
 }
 /**
@@ -21,7 +21,7 @@ export interface SlideComponent extends BaseComponent {
  *
  * @param Splide     - A Splide instance.
  * @param index      - A slide index.
- * @param slideIndex - A slide index for clones. This must be `-1` if the slide is not clone.
+ * @param slideIndex - A slide index for clones. This must be `-1` if the slide is not a clone.
  * @param slide      - A slide element.
  *
  * @return A Slide sub component.

+ 1 - 1
dist/types/components/Slides/Slide.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Slide.d.ts","sourceRoot":"","sources":["Slide.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmB5C;;;;GAIG;AACH,MAAM,WAAY,cAAe,SAAQ,aAAa;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAI,IAAI,CAAA;IAC1E,QAAQ,CAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAI,OAAO,CAAC;CACrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAI,cAAc,CAwM7G"}
+{"version":3,"file":"Slide.d.ts","sourceRoot":"","sources":["Slide.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqB5C;;;;GAIG;AACH,MAAM,WAAY,cAAe,SAAQ,aAAa;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAI,IAAI,CAAA;IAC3E,QAAQ,CAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAI,OAAO,CAAC;CACrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAI,cAAc,CAyM7G"}

+ 1 - 1
dist/types/components/Slides/Slides.d.ts

@@ -15,7 +15,7 @@ export interface SlidesComponent extends BaseComponent {
     remove(selector: SlideMatcher): void;
     forEach(iteratee: SlidesIteratee, excludeClones?: boolean): void;
     filter(matcher: SlideMatcher): SlideComponent[];
-    rule(prop: string, value: string | number, useContainer?: boolean): void;
+    style(prop: string, value: string | number, useContainer?: boolean): void;
     getLength(excludeClones?: boolean): number;
     isEnough(): boolean;
 }

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

@@ -1 +1 @@
-{"version":3,"file":"Slides.d.ts","sourceRoot":"","sources":["Slides.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAe,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAkB9E,OAAO,EAAS,cAAc,EAAE,MAAM,SAAS,CAAC;AAGhD;;;;GAIG;AACH,MAAM,WAAY,eAAgB,SAAQ,aAAa;IACrD,QAAQ,CAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAI,IAAI,CAAC;IACxE,GAAG,CAAE,aAAa,CAAC,EAAE,OAAO,GAAI,cAAc,EAAE,CAAC;IACjD,KAAK,CAAE,IAAI,EAAE,MAAM,GAAI,cAAc,EAAE,CAAC;IACxC,KAAK,CAAE,KAAK,EAAE,MAAM,GAAI,cAAc,GAAG,SAAS,CAAC;IACnD,GAAG,CAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAI,IAAI,CAAC;IAC/E,MAAM,CAAE,QAAQ,EAAE,YAAY,GAAI,IAAI,CAAC;IACvC,OAAO,CAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,OAAO,GAAI,IAAI,CAAC;IACnE,MAAM,CAAE,OAAO,EAAE,YAAY,GAAI,cAAc,EAAE,CAAC;IAClD,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAI,IAAI,CAAA;IAC1E,SAAS,CAAE,aAAa,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IAC7C,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,oBAAY,cAAc,GAAG,CAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAM,IAAI,CAAA;AAEvG;;;;GAIG;AACH,oBAAY,eAAe,GAAG,CAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAM,GAAG,CAAA;AAEvG;;;;GAIG;AACH,oBAAY,YAAY,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,eAAe,CAAC;AAExE;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,eAAe,CA2NlG"}
+{"version":3,"file":"Slides.d.ts","sourceRoot":"","sources":["Slides.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAe,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAkB9E,OAAO,EAAS,cAAc,EAAE,MAAM,SAAS,CAAC;AAGhD;;;;GAIG;AACH,MAAM,WAAY,eAAgB,SAAQ,aAAa;IACrD,QAAQ,CAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAI,IAAI,CAAC;IACxE,GAAG,CAAE,aAAa,CAAC,EAAE,OAAO,GAAI,cAAc,EAAE,CAAC;IACjD,KAAK,CAAE,IAAI,EAAE,MAAM,GAAI,cAAc,EAAE,CAAC;IACxC,KAAK,CAAE,KAAK,EAAE,MAAM,GAAI,cAAc,GAAG,SAAS,CAAC;IACnD,GAAG,CAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAI,IAAI,CAAC;IAC/E,MAAM,CAAE,QAAQ,EAAE,YAAY,GAAI,IAAI,CAAC;IACvC,OAAO,CAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,OAAO,GAAI,IAAI,CAAC;IACnE,MAAM,CAAE,OAAO,EAAE,YAAY,GAAI,cAAc,EAAE,CAAC;IAClD,KAAK,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAI,IAAI,CAAA;IAC3E,SAAS,CAAE,aAAa,CAAC,EAAE,OAAO,GAAI,MAAM,CAAC;IAC7C,QAAQ,IAAI,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,oBAAY,cAAc,GAAG,CAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAM,IAAI,CAAA;AAEvG;;;;GAIG;AACH,oBAAY,eAAe,GAAG,CAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAM,GAAG,CAAA;AAEvG;;;;GAIG;AACH,oBAAY,YAAY,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,eAAe,CAAC;AAExE;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,eAAe,CA8NlG"}

+ 0 - 19
dist/types/components/Style/Style.d.ts

@@ -1,19 +0,0 @@
-import { BaseComponent } from '../../types';
-/**
- * The interface for the Style component.
- *
- * @since 3.0.0
- */
-export interface StyleComponent extends BaseComponent {
-    rule(selector: string, prop: string, value: string | number): void;
-    ruleBy(target: string | HTMLElement, prop: string, value: string | number): void;
-}
-/**
- * The component for managing styles of the slider.
- *
- * @since 3.0.0
- *
- * @return A Style component object.
- */
-export declare function Style(): StyleComponent;
-//# sourceMappingURL=../../../../src/js/components/Style/Style.d.ts.map

+ 0 - 1
dist/types/components/Style/Style.d.ts.map

@@ -1 +0,0 @@
-{"version":3,"file":"Style.d.ts","sourceRoot":"","sources":["Style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C;;;;GAIG;AACH,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,IAAI,CAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAI,IAAI,CAAC;IACrE,MAAM,CAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAI,IAAI,CAAC;CACpF;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,IAAI,cAAc,CA6EtC"}

+ 1 - 2
dist/types/components/index.d.ts

@@ -1,10 +1,9 @@
 export { Options } from './Options/Options';
 export { Direction } from './Direction/Direction';
 export { Elements } from './Elements/Elements';
-export { Style } from './Style/Style';
 export { Slides } from './Slides/Slides';
-export { Clones } from './Clones/Clones';
 export { Layout } from './Layout/Layout';
+export { Clones } from './Clones/Clones';
 export { Move } from './Move/Move';
 export { Controller } from './Controller/Controller';
 export { Arrows } from './Arrows/Arrows';

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

@@ -1 +1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAS,mBAAmB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAO,uBAAuB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAW,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAY,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAW,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAY,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAY,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAW,eAAe,CAAC"}
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAS,mBAAmB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAO,uBAAuB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAY,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAW,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAU,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAY,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAQ,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAY,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAW,eAAe,CAAC"}

+ 0 - 16
dist/types/test/utils/utils.d.ts

@@ -52,21 +52,5 @@ export declare function keydown(key: string, target?: Window | Element): void;
  * @return A Promise instance.
  */
 export declare function wait(duration: number): Promise<void>;
-/**
- * Finds the CSSRule object.
- *
- * @param selector - A selector to find.
- *
- * @return A found CSSRule object.
- */
-export declare function findRule(selector: string): CSSStyleRule;
-/**
- * Finds the CSSRule object by ID.
- *
- * @param target - The element or ID.
- *
- * @return A found CSSRule object.
- */
-export declare function findRuleBy(target: string | HTMLElement): CSSStyleRule;
 export {};
 //# 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;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAE,QAAQ,EAAE,MAAM,GAAI,YAAY,CAMzD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAI,YAAY,CAEvE"}
+{"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"}

+ 1 - 1
dist/types/transitions/Fade/Fade.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Fade.d.ts","sourceRoot":"","sources":["Fade.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvE;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,mBAAmB,CAwCpG"}
+{"version":3,"file":"Fade.d.ts","sourceRoot":"","sources":["Fade.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvE;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAI,mBAAmB,CAqCpG"}

+ 4 - 0
dist/types/types/options.d.ts

@@ -124,6 +124,10 @@ export interface Options extends ResponsiveOptions {
      * where `tabindex="-1"` will be assigned when their ascendant slide is hidden.
      */
     focusableNodes?: string;
+    /**
+     * Determines whether to use the Transition component or not.
+     */
+    useScroll?: boolean;
     /**
      * Options for specific breakpoints.
      *

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


+ 3 - 9
dist/types/utils/dom/style/style.d.ts

@@ -1,10 +1,4 @@
-/**
- * The union for CSS style properties, such as "padding", "fontSize", etc.
- *
- * @since 0.1.0
- */
-export declare type CSSStyleProperties = Exclude<keyof CSSStyleDeclaration, number>;
-export declare function style(elm: HTMLElement, styles: Record<string, string | number>): void;
-export declare function style<K extends CSSStyleProperties>(elm: HTMLElement, styles: K): CSSStyleDeclaration[K];
-export declare function style(elm: HTMLElement, styles: string): string;
+export declare function style<K extends keyof CSSStyleDeclaration>(elm: HTMLElement, prop: K): CSSStyleDeclaration[K];
+export declare function style(elm: HTMLElement, prop: string): string;
+export declare function style(elm: HTMLElement, prop: string, value: string | number): void;
 //# sourceMappingURL=../../../../../src/js/utils/dom/style/style.d.ts.map

+ 1 - 1
dist/types/utils/dom/style/style.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["style.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,oBAAY,kBAAkB,GAAG,OAAO,CAAC,MAAM,mBAAmB,EAAE,MAAM,CAAC,CAAC;AAE5E,wBAAgB,KAAK,CACnB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GACtC,IAAI,CAAC;AAER,wBAAgB,KAAK,CAAC,CAAC,SAAS,kBAAkB,EAChD,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,CAAC,GACR,mBAAmB,CAAE,CAAC,CAAE,CAAC;AAE5B,wBAAgB,KAAK,CACnB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAAC"}
+{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["style.ts"],"names":[],"mappings":"AAGA,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,mBAAmB,EACvD,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,CAAC,GACN,mBAAmB,CAAE,CAAC,CAAE,CAAC;AAE5B,wBAAgB,KAAK,CACnB,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,CAAC;AAEV,wBAAgB,KAAK,CACnB,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,MAAM,GACrB,IAAI,CAAC"}

+ 1 - 1
package-lock.json

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

+ 1 - 1
package.json

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

+ 1 - 1
src/js/components/Autoplay/Autoplay.ts

@@ -161,7 +161,7 @@ export function Autoplay( Splide: Splide, Components: Components, options: Optio
     const { bar } = Elements;
 
     if ( bar ) {
-      style( bar, { width: `${ rate * 100 }%` } );
+      style( bar, 'width', `${ rate * 100 }%` );
     }
 
     emit( EVENT_AUTOPLAY_PLAYING, rate );

+ 2 - 1
src/js/components/Clones/Clones.ts

@@ -55,6 +55,7 @@ export function Clones( Splide: Splide, Components: Components, options: Options
   function init(): void {
     if ( ( cloneCount = computeCloneCount() ) ) {
       generate( cloneCount );
+      emit( EVENT_RESIZE );
     }
   }
 
@@ -79,7 +80,7 @@ export function Clones( Splide: Splide, Components: Components, options: Options
    * Observes the required clone count and refreshes the slider if necessary.
    */
   function observe(): void {
-    if ( cloneCount !== computeCloneCount() ) {
+    if ( cloneCount < computeCloneCount() ) {
       emit( EVENT_REFRESH );
     }
   }

+ 54 - 16
src/js/components/Controller/Controller.ts

@@ -1,4 +1,4 @@
-import { EVENT_REFRESH, EVENT_SCROLLED, EVENT_UPDATED } from '../../constants/events';
+import { EVENT_REFRESH, EVENT_UPDATED } from '../../constants/events';
 import { DEFAULT_EVENT_PRIORITY } from '../../constants/priority';
 import { LOOP, SLIDE } from '../../constants/types';
 import { EventInterface } from '../../constructors';
@@ -14,6 +14,7 @@ import { approximatelyEqual, between, clamp, floor, isString, isUndefined, max }
  */
 export interface ControllerComponent extends BaseComponent {
   go( control: number | string, allowSameIndex?: boolean, callback?: AnyFunction ): void;
+  scroll( destination: number, useIndex?: boolean, snap?: boolean, duration?: number, callback?: AnyFunction ): void;
   getNext( destination?: boolean ): number;
   getPrev( destination?: boolean ): number;
   getEnd(): number;
@@ -21,6 +22,7 @@ export interface ControllerComponent extends BaseComponent {
   getIndex( prev?: boolean ): number;
   toIndex( page: number ): number;
   toPage( index: number ): number;
+  toDest( position: number ): number;
   hasFocus(): boolean;
 }
 
@@ -40,7 +42,8 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
   const { Move } = Components;
   const { getPosition, getLimit } = Move;
   const { isEnough, getLength } = Components.Slides;
-  const isLoop = Splide.is( LOOP );
+  const isLoop  = Splide.is( LOOP );
+  const isSlide = Splide.is( SLIDE );
 
   /**
    * The current index.
@@ -73,7 +76,6 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
   function mount(): void {
     init();
     on( [ EVENT_UPDATED, EVENT_REFRESH ], init, DEFAULT_EVENT_PRIORITY - 1 );
-    on( EVENT_SCROLLED, reindex, 0 );
   }
 
   /**
@@ -87,13 +89,6 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
     currIndex  = clamp( currIndex, 0, slideCount - 1 );
   }
 
-  /**
-   * Calculates the index by the current position and updates the current index.
-   */
-  function reindex(): void {
-    setIndex( Move.toIndex( getPosition() ) );
-  }
-
   /**
    * Moves the slider by the control pattern.
    *
@@ -104,15 +99,44 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
    * @param callback       - Optional. A callback function invoked after transition ends.
    */
   function go( control: number | string, allowSameIndex?: boolean, callback?: AnyFunction ): void {
-    const dest  = parse( control );
-    const index = loop( dest );
+    const dest = parse( control );
 
-    if ( index > -1 && ! Move.isBusy() && ( allowSameIndex || index !== currIndex ) ) {
-      setIndex( index );
-      Move.move( dest, index, prevIndex, callback );
+    if ( options.useScroll ) {
+      scroll( dest, true, true, options.speed, callback );
+    } else {
+      const index = loop( dest );
+
+      if ( index > -1 && ! Move.isBusy() && ( allowSameIndex || index !== currIndex ) ) {
+        setIndex( index );
+        Move.move( dest, index, prevIndex, callback );
+      }
     }
   }
 
+  /**
+   * Scrolls the slider to the specified destination with updating indices.
+   *
+   * @param destination - A position or an index to scroll to.
+   * @param useIndex    - Optional. Whether to use an index as a destination or not.
+   * @param snap        - Optional. Whether to snap the closest slide or not.
+   * @param duration    - Optional. Specifies the scroll duration.
+   * @param callback    - Optional. A callback function invoked after scroll ends.
+   */
+  function scroll(
+    destination: number,
+    useIndex?: boolean,
+    snap?: boolean,
+    duration?: number,
+    callback?: AnyFunction
+  ): void {
+    const dest = useIndex ? destination : toDest( destination );
+
+    Components.Scroll.scroll( useIndex || snap ? Move.toPosition( dest, true ) : destination, duration, () => {
+      setIndex( Move.toIndex( Move.getPosition() ) );
+      callback && callback();
+    } );
+  }
+
   /**
    * Parses the control and returns a slide index.
    *
@@ -176,7 +200,7 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
     const number = perMove || hasFocus() ? 1 : perPage;
     const dest   = computeDestIndex( currIndex + number * ( prev ? -1 : 1 ), currIndex );
 
-    if ( dest === -1 && Splide.is( SLIDE ) ) {
+    if ( dest === -1 && isSlide ) {
       if ( ! approximatelyEqual( getPosition(), getLimit( ! prev ), 1 ) ) {
         return prev ? 0 : getEnd();
       }
@@ -285,6 +309,18 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
     return index;
   }
 
+  /**
+   * Converts the destination position to the dest index.
+   *
+   * @param destination - A position to convert.
+   *
+   * @return A dest index.
+   */
+  function toDest( destination: number ): number {
+    const closest = Move.toIndex( destination );
+    return isSlide ? clamp( closest, 0, getEnd() ) : closest;
+  }
+
   /**
    * Sets a new index and retains old one.
    *
@@ -318,6 +354,7 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
   return {
     mount,
     go,
+    scroll,
     getNext,
     getPrev,
     getEnd,
@@ -325,6 +362,7 @@ export function Controller( Splide: Splide, Components: Components, options: Opt
     getIndex,
     toIndex,
     toPage,
+    toDest,
     hasFocus,
   };
 }

+ 1 - 1
src/js/components/Cover/Cover.ts

@@ -68,7 +68,7 @@ export function Cover( Splide: Splide, Components: Components, options: Options
    * @param Slide - A SlideComponent object where the image belongs.
    */
   function toggle( cover: boolean, img: HTMLImageElement, Slide: SlideComponent ): void {
-    Slide.rule( 'background', cover ? `center/cover no-repeat url("${ img.src }")` : '', true );
+    Slide.style( 'background', cover ? `center/cover no-repeat url("${ img.src }")` : '', true );
     display( img, cover ? 'none' : '' );
   }
 

+ 0 - 32
src/js/components/Cover/test/general.test.ts

@@ -1,32 +0,0 @@
-import { CLASS_SLIDE } from '../../../constants/classes';
-import { findRule, init } from '../../../test';
-import { URL } from '../../../test/fixtures/constants';
-
-
-describe( 'Cover', () => {
-  test( 'can set the image in the slide to the background image.', () => {
-    const splide = init( { cover: true } );
-    const slides = splide.root.querySelectorAll<HTMLElement>( `.${ CLASS_SLIDE }` );
-    const rule1  = findRule( `#${ slides[ 0 ].id }` );
-    const rule2  = findRule( `#${ slides[ 1 ].id }` );
-
-    expect( rule1.style.background ).toBe( `center/cover no-repeat url("${ URL }/0.jpg")` );
-    expect( rule2.style.background ).toBe( `center/cover no-repeat url("${ URL }/1.jpg")` );
-
-    splide.destroy();
-  } );
-
-  test( 'can remove the background image on destroy.', () => {
-    const splide = init( { cover: true } );
-    const slides = splide.root.querySelectorAll<HTMLElement>( `.${ CLASS_SLIDE }` );
-    const rule1  = findRule( `#${ slides[ 0 ].id }` );
-    const rule2  = findRule( `#${ slides[ 1 ].id }` );
-
-    splide.Components.Cover.destroy();
-
-    expect( rule1.style.background ).toBe( '' );
-    expect( rule2.style.background ).toBe( '' );
-
-    splide.destroy();
-  } );
-} );

+ 5 - 17
src/js/components/Drag/Drag.ts

@@ -3,7 +3,7 @@ import { FADE, LOOP, SLIDE } from '../../constants/types';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
-import { abs, clamp, min, noop, prevent, sign } from '../../utils';
+import { abs, min, noop, prevent, sign } from '../../utils';
 import { FRICTION, LOG_INTERVAL, POINTER_DOWN_EVENTS, POINTER_MOVE_EVENTS, POINTER_UP_EVENTS } from './constants';
 
 
@@ -34,7 +34,6 @@ export function Drag( Splide: Splide, Components: Components, options: Options )
   const { resolve, orient } = Components.Direction;
   const { getPosition, exceededLimit } = Move;
   const listenerOptions = { passive: false, capture: true };
-  const isSlide         = Splide.is( SLIDE );
 
   /**
    * The base slider position to calculate the delta of coords.
@@ -95,6 +94,7 @@ export function Drag( Splide: Splide, Components: Components, options: Options )
     bind( track, POINTER_UP_EVENTS, noop, listenerOptions );
     bind( track, POINTER_DOWN_EVENTS, onPointerDown, listenerOptions );
     bind( track, 'click', onClick, { capture: true } );
+    bind( track, 'dragstart', prevent );
 
     on( [ EVENT_MOUNTED, EVENT_UPDATED ], init );
   }
@@ -191,11 +191,11 @@ export function Drag( Splide: Splide, Components: Components, options: Options )
         const destination = computeDestination( velocity );
 
         if ( isFree ) {
-          Scroll.scroll( destination );
+          Controller.scroll( destination );
         } else if ( Splide.is( FADE ) ) {
           Controller.go( Splide.index + orient( sign( velocity ) ) );
         } else {
-          Controller.go( computeIndex( destination ), true );
+          Controller.go( Controller.toDest( destination ), true );
         }
 
         prevent( e );
@@ -277,18 +277,6 @@ export function Drag( Splide: Splide, Components: Components, options: Options )
     );
   }
 
-  /**
-   * Converts the destination to the slide index.
-   *
-   * @param destination - The target destination.
-   *
-   * @return The destination index.
-   */
-  function computeIndex( destination: number ): number {
-    const dest = Move.toIndex( destination );
-    return isSlide ? clamp( dest, 0, Controller.getEnd() ) : dest;
-  }
-
   /**
    * Returns the `pageX` and `pageY` coordinates provided by the event.
    * Be aware that IE does not support both TouchEvent and MouseEvent constructors.
@@ -333,7 +321,7 @@ export function Drag( Splide: Splide, Components: Components, options: Options )
    * @return The constrained diff.
    */
   function constrain( diff: number ): number {
-    return diff / ( hasExceeded && isSlide ? FRICTION : 1 );
+    return diff / ( hasExceeded && Splide.is( SLIDE ) ? FRICTION : 1 );
   }
 
   /**

+ 17 - 1
src/js/components/Elements/Elements.ts

@@ -21,7 +21,19 @@ import { PROJECT_CODE } from '../../constants/project';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { BaseComponent, Components, Options } from '../../types';
-import { addClass, assert, assign, child, children, empty, push, query, removeClass, uniqueId } from '../../utils';
+import {
+  addClass,
+  assert,
+  assign,
+  child,
+  children,
+  empty,
+  push,
+  query,
+  removeAttribute,
+  removeClass,
+  uniqueId,
+} from '../../utils';
 
 
 /**
@@ -114,6 +126,10 @@ export function Elements( Splide: Splide, Components: Components, options: Optio
    * Destroys the component.
    */
   function destroy(): void {
+    [ root, track, list ].forEach( elm => {
+      removeAttribute( elm, 'style' );
+    } );
+
     empty( slides );
     removeClass( root, classes );
   }

+ 10 - 12
src/js/components/Layout/Layout.ts

@@ -33,7 +33,6 @@ export interface LayoutComponent extends BaseComponent {
 export function Layout( Splide: Splide, Components: Components, options: Options ): LayoutComponent {
   const { on, bind, emit } = EventInterface( Splide );
   const { Slides } = Components;
-  const { ruleBy } = Components.Style;
   const { resolve } = Components.Direction;
   const { track, list } = Components.Elements;
   const { getAt } = Slides;
@@ -48,7 +47,6 @@ export function Layout( Splide: Splide, Components: Components, options: Options
    */
   function mount(): void {
     init();
-
     bind( window, 'resize load', Throttle( emit.bind( this, EVENT_RESIZE ) ) );
     on( [ EVENT_UPDATED, EVENT_REFRESH ], init );
     on( EVENT_RESIZE, resize );
@@ -61,14 +59,10 @@ export function Layout( Splide: Splide, Components: Components, options: Options
   function init(): void {
     vertical = options.direction === TTB;
 
-    ruleBy( Splide.root, 'maxWidth', unit( options.width ) );
-    ruleBy( track, resolve( 'paddingLeft' ), cssPadding( false ) );
-    ruleBy( track, resolve( 'paddingRight' ), cssPadding( true ) );
-
-    Slides.rule( resolve( 'marginRight' ), unit( options.gap ) );
-    Slides.rule( 'width', cssSlideWidth() );
+    style( Splide.root, 'maxWidth', unit( options.width ) );
+    style( track, resolve( 'paddingLeft' ), cssPadding( false ) );
+    style( track, resolve( 'paddingRight' ), cssPadding( true ) );
 
-    setSlidesHeight();
     resize();
   }
 
@@ -76,8 +70,12 @@ export function Layout( Splide: Splide, Components: Components, options: Options
    * Updates dimensions of some elements when the slider is resized.
    */
   function resize(): void {
-    ruleBy( track, 'height', cssTrackHeight() );
-    options.heightRatio && setSlidesHeight();
+    style( track, 'height', cssTrackHeight() );
+
+    Slides.style( resolve( 'marginRight' ), unit( options.gap ) );
+    Slides.style( 'width', cssSlideWidth() || null );
+    setSlidesHeight();
+
     emit( EVENT_RESIZED );
   }
 
@@ -85,7 +83,7 @@ export function Layout( Splide: Splide, Components: Components, options: Options
    * Updates the height of slides or their container elements if available.
    */
   function setSlidesHeight(): void {
-    Slides.rule( 'height', cssSlideHeight(), true );
+    Slides.style( 'height', cssSlideHeight(), true );
   }
 
   /**

+ 11 - 12
src/js/components/Layout/test/general.test.ts

@@ -1,53 +1,52 @@
 import { EVENT_RESIZE } from '../../../constants/events';
-import { findRuleBy, init } from '../../../test';
+import { init } from '../../../test';
 
 
 describe( 'Layout', () => {
   test( 'can set the max width of the slider.', () => {
     const splide = init( { width: 100 } );
-    const rule   = findRuleBy( splide.root );
 
-    expect( rule.style.maxWidth ).toBe( '100px' );
+    expect( splide.root.style.maxWidth ).toBe( '100px' );
     splide.destroy();
   } );
 
   test( 'should init the component again when options are updated.', () => {
     const splide = init( { width: 100 } );
-    const rule   = findRuleBy( splide.root );
+    const style  = splide.root.style;
 
-    expect( rule.style.maxWidth ).toBe( '100px' );
+    expect( style.maxWidth ).toBe( '100px' );
 
     splide.options = { width: 200 };
 
-    expect( rule.style.maxWidth ).toBe( '200px' );
+    expect( style.maxWidth ).toBe( '200px' );
 
     splide.destroy();
   } );
 
   test( 'should init the component again when the splide is refreshed.', () => {
     const splide = init( { width: 100 } );
-    const rule   = findRuleBy( splide.root );
+    const style  = splide.root.style;
 
-    expect( rule.style.maxWidth ).toBe( '100px' );
+    expect( style.maxWidth ).toBe( '100px' );
 
     splide.options.width = 200;
     splide.refresh();
 
-    expect( rule.style.maxWidth ).toBe( '200px' );
+    expect( style.maxWidth ).toBe( '200px' );
 
     splide.destroy();
   } );
 
   test( 'should update the slide height when the window is resized.', () => {
     const splide = init( { width: 1000, heightRatio: 0.5 } );
-    const rule   = findRuleBy( splide.Components.Elements.slides[ 0 ] );
+    const style  = splide.Components.Elements.slides[ 0 ].style;
 
-    expect( rule.style.height ).toBe( '500px' );
+    expect( style.height ).toBe( '500px' );
 
     splide.options.heightRatio = 0.2;
     splide.emit( EVENT_RESIZE );
 
-    expect( rule.style.height ).toBe( '200px' );
+    expect( style.height ).toBe( '200px' );
 
     splide.destroy();
   } );

+ 24 - 50
src/js/components/Layout/test/ltr.test.ts

@@ -1,102 +1,77 @@
-import { findRuleBy, init } from '../../../test';
+import { init } from '../../../test';
 import { SLIDER_WIDTH } from '../../../test/fixtures/constants';
 
 
 describe( 'Layout in the LTR mode', () => {
   test( 'can set paddings to the track element.', () => {
     const splide1 = init( { padding: '2rem' } );
-    const rule1   = findRuleBy( splide1.Components.Elements.track );
+    const track1  = splide1.Components.Elements.track;
 
-    expect( rule1.style.paddingLeft ).toBe( '2rem' );
-    expect( rule1.style.paddingRight ).toBe( '2rem' );
+    expect( track1.style.paddingLeft ).toBe( '2rem' );
+    expect( track1.style.paddingRight ).toBe( '2rem' );
     splide1.destroy();
 
     const splide2 = init( { padding: { left: '4%', right: '5%' } } );
-    const rule2   = findRuleBy( splide2.Components.Elements.track );
+    const track2  = splide2.Components.Elements.track;
 
-    expect( rule2.style.paddingLeft ).toBe( '4%' );
-    expect( rule2.style.paddingRight ).toBe( '5%' );
+    expect( track2.style.paddingLeft ).toBe( '4%' );
+    expect( track2.style.paddingRight ).toBe( '5%' );
     splide2.destroy();
 
     const splide3 = init( { padding: { left: '4%' } } );
-    const rule3   = findRuleBy( splide3.Components.Elements.track );
+    const track3  = splide3.Components.Elements.track;
 
-    expect( rule3.style.paddingLeft ).toBe( '4%' );
-    expect( rule3.style.paddingRight ).toBe( '0px' );
+    expect( track3.style.paddingLeft ).toBe( '4%' );
+    expect( track3.style.paddingRight ).toBe( '0px' );
     splide3.destroy();
   } );
 
   test( 'can set margin as a gap.', () => {
     const splide = init( { gap: '2rem' } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
+    const slides = splide.Components.Elements.slides;
 
-    expect( rule1.style.marginRight ).toBe( '2rem' );
-    expect( rule2.style.marginRight ).toBe( '2rem' );
+    expect( slides[ 0 ].style.marginRight ).toBe( '2rem' );
+    expect( slides[ 1 ].style.marginRight ).toBe( '2rem' );
     splide.destroy();
   } );
 
-  test( 'can set slide width.', () => {
-    const splide1 = init( { perPage: 3 } );
-    const rule1   = findRuleBy( splide1.Components.Elements.slides[ 0 ] );
-
-    expect( rule1.style.width ).toBe( 'calc((100%)/3)' );
-    splide1.destroy();
-
-    const splide2 = init( { perPage: 3, gap: '2rem' } );
-    const rule2   = findRuleBy( splide2.Components.Elements.slides[ 0 ] );
-
-    expect( rule2.style.width ).toBe( 'calc((100% + 2rem)/3 - 2rem)' );
-    splide2.destroy();
-  } );
-
   test( 'can fix the slide width.', () => {
     const splide = init( { fixedWidth: 100 } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
 
-    expect( rule1.style.width ).toBe( '100px' );
-    expect( rule2.style.width ).toBe( '100px' );
+    expect( splide.Components.Elements.slides[ 0 ].style.width ).toBe( '100px' );
+    expect( splide.Components.Elements.slides[ 1 ].style.width ).toBe( '100px' );
     splide.destroy();
   } );
 
   test( 'can set the slide height.', () => {
     const splide = init( { height: '10rem' } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
 
-    expect( rule1.style.height ).toBe( '10rem' );
-    expect( rule2.style.height ).toBe( '10rem' );
+    expect( splide.Components.Elements.slides[ 0 ].style.height ).toBe( '10rem' );
+    expect( splide.Components.Elements.slides[ 1 ].style.height ).toBe( '10rem' );
     splide.destroy();
   } );
 
   test( 'can set the slide height by ratio against the slider width.', () => {
     const splide = init( { width: 500, heightRatio: 0.5 } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
 
-    expect( rule1.style.height ).toBe( '250px' );
-    expect( rule2.style.height ).toBe( '250px' );
+    expect( splide.Components.Elements.slides[ 0 ].style.height ).toBe( '250px' );
+    expect( splide.Components.Elements.slides[ 1 ].style.height ).toBe( '250px' );
     splide.destroy();
   } );
 
   test( 'can fix the slide height.', () => {
     const splide = init( { fixedHeight: 100 } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
 
-    expect( rule1.style.height ).toBe( '100px' );
-    expect( rule2.style.height ).toBe( '100px' );
+    expect( splide.Components.Elements.slides[ 0 ].style.height ).toBe( '100px' );
+    expect( splide.Components.Elements.slides[ 1 ].style.height ).toBe( '100px' );
     splide.destroy();
   } );
 
   test( 'should not set the slide width when the autoWidth is true.', () => {
     const splide = init( { autoWidth: true } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
 
-    expect( rule1.style.width ).toBe( '' );
-    expect( rule2.style.width ).toBe( '' );
+    expect( splide.Components.Elements.slides[ 0 ].style.width ).toBe( '' );
+    expect( splide.Components.Elements.slides[ 1 ].style.width ).toBe( '' );
     splide.destroy();
   } );
 
@@ -122,9 +97,8 @@ describe( 'Layout in the LTR mode', () => {
 
   test( 'should not set the track width.', () => {
     const splide = init( { height: 100 } );
-    const rule   = findRuleBy( splide.Components.Elements.track );
 
-    expect( rule.style.height ).toBe( '' );
+    expect( splide.Components.Elements.track.style.height ).toBe( '' );
     splide.destroy();
   } );
 } );

+ 3 - 5
src/js/components/Layout/test/rtl.test.ts

@@ -1,15 +1,13 @@
 import { RTL } from '../../../constants/directions';
-import { findRuleBy, init } from '../../../test';
+import { init } from '../../../test';
 
 
 describe( 'Layout in the RTL mode', () => {
   test( 'can set margin as a gap.', () => {
     const splide = init( { direction: RTL, gap: '2rem' } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
 
-    expect( rule1.style.marginLeft ).toBe( '2rem' );
-    expect( rule2.style.marginLeft ).toBe( '2rem' );
+    expect( splide.Components.Elements.slides[ 0 ].style.marginLeft ).toBe( '2rem' );
+    expect( splide.Components.Elements.slides[ 1 ].style.marginLeft ).toBe( '2rem' );
     splide.destroy();
   } );
 } );

+ 20 - 29
src/js/components/Layout/test/ttb.test.ts

@@ -1,80 +1,71 @@
 import { TTB } from '../../../constants/directions';
-import { findRuleBy, init } from '../../../test';
+import { init } from '../../../test';
 
 
 describe( 'Layout in the TTB mode', () => {
   test( 'can set paddings to the track element.', () => {
     const splide1 = init( { height: 100, direction: TTB, padding: '2rem' } );
-    const rule1   = findRuleBy( splide1.Components.Elements.track );
+    const track1  = splide1.Components.Elements.track;
 
-    expect( rule1.style.paddingTop ).toBe( '2rem' );
-    expect( rule1.style.paddingBottom ).toBe( '2rem' );
+    expect( track1.style.paddingTop ).toBe( '2rem' );
+    expect( track1.style.paddingBottom ).toBe( '2rem' );
     splide1.destroy();
 
     const splide2 = init( { height: 100, direction: TTB, padding: { top: '4%', bottom: '5%' } } );
-    const rule2   = findRuleBy( splide2.Components.Elements.track );
+    const track2  = splide2.Components.Elements.track;
 
-    expect( rule2.style.paddingTop ).toBe( '4%' );
-    expect( rule2.style.paddingBottom ).toBe( '5%' );
+    expect( track2.style.paddingTop ).toBe( '4%' );
+    expect( track2.style.paddingBottom ).toBe( '5%' );
     splide2.destroy();
 
     const splide3 = init( { height: 100, direction: TTB, padding: { top: '4%' } } );
-    const rule3   = findRuleBy( splide3.Components.Elements.track );
+    const track3  = splide3.Components.Elements.track;
 
-    expect( rule3.style.paddingTop ).toBe( '4%' );
-    expect( rule3.style.paddingBottom ).toBe( '0px' );
+    expect( track3.style.paddingTop ).toBe( '4%' );
+    expect( track3.style.paddingBottom ).toBe( '0px' );
     splide3.destroy();
   } );
 
   test( 'can set margin as a gap.', () => {
     const splide = init( { height: 100, direction: TTB, gap: '2rem' } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
+    const slides = splide.Components.Elements.slides;
 
-    expect( rule1.style.marginBottom ).toBe( '2rem' );
-    expect( rule2.style.marginBottom ).toBe( '2rem' );
+    expect( slides[ 0 ].style.marginBottom ).toBe( '2rem' );
+    expect( slides[ 1 ].style.marginBottom ).toBe( '2rem' );
     splide.destroy();
   } );
 
   test( 'can set height of the track element.', () => {
     const splide = init( { height: 100, direction: TTB } );
-    const rule   = findRuleBy( splide.Components.Elements.track );
-
-    expect( rule.style.height ).toBe( 'calc(100px - 0px - 0px)' );
+    expect( splide.Components.Elements.track.style.height ).toBe( 'calc(100px - 0px - 0px)' );
     splide.destroy();
   } );
 
   test( 'can set height of the track element with subtracting paddings.', () => {
     const splide = init( { height: 100, direction: TTB, padding: { top: '1rem', bottom: '2rem' } } );
-    const rule   = findRuleBy( splide.Components.Elements.track );
-
-    expect( rule.style.height ).toBe( 'calc(100px - 1rem - 2rem)' );
+    expect( splide.Components.Elements.track.style.height ).toBe( 'calc(100px - 1rem - 2rem)' );
     splide.destroy();
   } );
 
   test( 'can set height of the track element by heightRatio.', () => {
     const splide = init( { width: 500, heightRatio: 0.5, direction: TTB } );
-    const rule   = findRuleBy( splide.Components.Elements.track );
 
-    expect( rule.style.height ).toBe( 'calc(250px - 0px - 0px)' );
+    expect( splide.Components.Elements.track.style.height ).toBe( 'calc(250px - 0px - 0px)' );
     splide.destroy();
   } );
 
   test( 'can set height of the track element by heightRatio with subtracting paddings.', () => {
     const splide = init( { width: 500, heightRatio: 0.5, direction: TTB, padding: { top: '1rem', bottom: '2rem' } } );
-    const rule   = findRuleBy( splide.Components.Elements.track );
-
-    expect( rule.style.height ).toBe( 'calc(250px - 1rem - 2rem)' );
+    expect( splide.Components.Elements.track.style.height ).toBe( 'calc(250px - 1rem - 2rem)' );
     splide.destroy();
   } );
 
   test( 'should not set the slide width.', () => {
     const splide = init( { height: 100, direction: TTB } );
-    const rule1  = findRuleBy( splide.Components.Elements.slides[ 0 ] );
-    const rule2  = findRuleBy( splide.Components.Elements.slides[ 1 ] );
+    const slides = splide.Components.Elements.slides;
 
-    expect( rule1.style.width ).toBe( '' );
-    expect( rule2.style.width ).toBe( '' );
+    expect( slides[ 0 ].style.width ).toBe( '' );
+    expect( slides[ 1 ].style.width ).toBe( '' );
     splide.destroy();
   } );
 

+ 18 - 3
src/js/components/Move/Move.ts

@@ -24,6 +24,7 @@ export interface MoveComponent extends BaseComponent {
   move( dest: number, index: number, prev: number, callback?: AnyFunction ): void;
   jump( index: number ): void;
   translate( position: number, preventLoop?: boolean ): void;
+  shift( position: number, backwards: boolean ): number;
   cancel(): void;
   toIndex( position: number ): number;
   toPosition( index: number, trimming?: boolean ): number;
@@ -146,15 +147,28 @@ export function Move( Splide: Splide, Components: Components, options: Options )
       const exceededMax = exceededLimit( true, position ) && diff > 0;
 
       if ( exceededMin || exceededMax ) {
-        const excess = position - getLimit( exceededMax );
-        const size   = sliderSize();
-        position -= sign( excess ) * size * ceil( abs( excess ) / size );
+        position = shift( position, exceededMax );
       }
     }
 
     return position;
   }
 
+  /**
+   * Adds or subtracts the slider width to the provided position.
+   *
+   * @param position  - A position to shift.
+   * @param backwards - Determines whether to shift the slider backwards or forwards.
+   *
+   * @return The shifted position.
+   */
+  function shift( position: number, backwards: boolean ): number {
+    const excess = position - getLimit( backwards );
+    const size   = sliderSize();
+    position -= sign( excess ) * size * ceil( abs( excess ) / size );
+    return position;
+  }
+
   /**
    * Cancels transition.
    */
@@ -281,6 +295,7 @@ export function Move( Splide: Splide, Components: Components, options: Options )
     move,
     jump,
     translate,
+    shift,
     cancel,
     toIndex,
     toPosition,

+ 3 - 4
src/js/components/Move/test/general.test.ts

@@ -1,4 +1,4 @@
-import { findRuleBy, fire, init } from '../../../test';
+import { fire, init } from '../../../test';
 
 
 describe( 'Move', () => {
@@ -49,12 +49,11 @@ describe( 'Move', () => {
     const { list } = splide.Components.Elements;
 
     Move.move( 1, 1, -1 );
-    const rule = findRuleBy( list );
 
-    expect( rule.style.transition ).not.toBe( '' );
+    expect( list.style.transition ).not.toBe( '' );
 
     Move.cancel();
-    expect( rule.style.transition ).toBe( '' );
+    expect( list.style.transition ).toBe( '' );
 
     splide.destroy();
   } );

+ 24 - 7
src/js/components/Scroll/Scroll.ts

@@ -2,8 +2,8 @@ import { EVENT_MOVE, EVENT_REFRESH, EVENT_SCROLL, EVENT_SCROLLED, EVENT_UPDATED
 import { SLIDE } from '../../constants/types';
 import { EventInterface, RequestInterval, RequestIntervalInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
-import { BaseComponent, Components, Options } from '../../types';
-import { abs, max } from '../../utils';
+import { AnyFunction, BaseComponent, Components, Options } from '../../types';
+import { abs, between, max } from '../../utils';
 import { BASE_VELOCITY, BOUNCE_DIFF_THRESHOLD, BOUNCE_DURATION, FRICTION_FACTOR, MIN_DURATION } from './constants';
 
 
@@ -13,7 +13,7 @@ import { BASE_VELOCITY, BOUNCE_DIFF_THRESHOLD, BOUNCE_DURATION, FRICTION_FACTOR,
  * @since 3.0.0
  */
 export interface ScrollComponent extends BaseComponent {
-  scroll( position: number, duration?: number ): void;
+  scroll( position: number, duration?: number, callback?: AnyFunction ): void;
   cancel(): void;
 }
 
@@ -38,6 +38,8 @@ export function Scroll( Splide: Splide, Components: Components, options: Options
    */
   let interval: RequestIntervalInterface;
 
+  let scrollCallback: AnyFunction;
+
   /**
    * Called when the component is mounted.
    */
@@ -51,13 +53,20 @@ export function Scroll( Splide: Splide, Components: Components, options: Options
    *
    * @param destination        - The destination to scroll to.
    * @param duration           - Optional. The scroll duration. If omitted, calculates it by the distance.
+   * @param callback           - Optional. A callback invoked after scroll ends.
    * @param suppressConstraint - Optional. Whether to suppress constraint process when the slider exceeds bounds.
    */
-  function scroll( destination: number, duration?: number, suppressConstraint?: boolean ): void {
+  function scroll(
+    destination: number,
+    duration?: number,
+    callback?: AnyFunction,
+    suppressConstraint?: boolean
+  ): void {
     const start = getPosition();
     let friction = 1;
 
-    duration = duration || computeDuration( abs( destination - start ) );
+    duration       = duration || computeDuration( abs( destination - start ) );
+    scrollCallback = callback;
     clear();
 
     interval = RequestInterval( duration, onScrolled, rate => {
@@ -86,13 +95,21 @@ export function Scroll( Splide: Splide, Components: Components, options: Options
    * @param backwards - The direction the slider is going towards.
    */
   function bounce( backwards: boolean ): void {
-    scroll( getLimit( ! backwards ), BOUNCE_DURATION, true );
+    scroll( getLimit( ! backwards ), BOUNCE_DURATION, null, true );
   }
 
   /**
-   * Called when scroll ends or is canceled.
+   * Called when scroll ends or has been just canceled.
    */
   function onScrolled(): void {
+    const position = getPosition();
+    const index = Move.toIndex( position );
+
+    if ( ! between( index, 0, Splide.length - 1 ) ) {
+      Move.translate( Move.shift( position, index > 0 ), true );
+    }
+
+    scrollCallback && scrollCallback();
     emit( EVENT_SCROLLED );
   }
 

+ 9 - 6
src/js/components/Slides/Slide.ts

@@ -38,6 +38,7 @@ import {
   child,
   floor,
   format,
+  getAttribute,
   hasClass,
   min,
   pad,
@@ -46,6 +47,7 @@ import {
   removeAttribute,
   removeClass,
   setAttribute,
+  style as _style,
   toggleClass,
 } from '../../utils';
 
@@ -61,7 +63,7 @@ export interface  SlideComponent extends BaseComponent {
   slide: HTMLElement;
   container: HTMLElement;
   isClone: boolean;
-  rule( prop: string, value: string | number, useContainer?: boolean ): void
+  style( prop: string, value: string | number, useContainer?: boolean ): void
   isWithin( from: number, distance: number ): boolean;
 }
 
@@ -72,7 +74,7 @@ export interface  SlideComponent extends BaseComponent {
  *
  * @param Splide     - A Splide instance.
  * @param index      - A slide index.
- * @param slideIndex - A slide index for clones. This must be `-1` if the slide is not clone.
+ * @param slideIndex - A slide index for clones. This must be `-1` if the slide is not a clone.
  * @param slide      - A slide element.
  *
  * @return A Slide sub component.
@@ -82,6 +84,7 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
   const { Components, root, options } = Splide;
   const { isNavigation, updateOnMove } = options;
   const { resolve } = Components.Direction;
+  const styles         = getAttribute( slide, 'style' );
   const isClone        = slideIndex > -1;
   const container      = child( slide, `.${ CLASS_CONTAINER }` );
   const focusableNodes = options.focusableNodes && queryAll( slide, options.focusableNodes );
@@ -135,6 +138,7 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
     destroyEvents();
     removeClass( slide, STATUS_CLASSES );
     removeAttribute( slide, ALL_ATTRIBUTES );
+    setAttribute( slide, 'style', styles );
   }
 
   /**
@@ -216,9 +220,8 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
    * @param value        - A CSS value to add.
    * @param useContainer - Optional. Determines whether to apply the rule to the container or not.
    */
-  function rule( prop: string, value: string | number, useContainer?: boolean ): void {
-    const selector = `#${ slide.id }${ container && useContainer ? ` > .${ CLASS_CONTAINER }` : '' }`;
-    Components.Style.rule( selector, prop, value );
+  function style( prop: string, value: string | number, useContainer?: boolean ): void {
+    _style( ( useContainer && container ) || slide, prop, value );
   }
 
   /**
@@ -274,7 +277,7 @@ export function Slide( Splide: Splide, index: number, slideIndex: number, slide:
     isClone,
     mount,
     destroy,
-    rule,
+    style,
     isWithin,
   };
 }

+ 8 - 5
src/js/components/Slides/Slides.ts

@@ -1,4 +1,4 @@
-import { EVENT_REFRESH, EVENT_RESIZE } from '../../constants/events';
+import { EVENT_MOUNTED, EVENT_REFRESH, EVENT_RESIZE } from '../../constants/events';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { AnyFunction, BaseComponent, Components, Options } from '../../types';
@@ -36,7 +36,7 @@ export interface  SlidesComponent extends BaseComponent {
   remove( selector: SlideMatcher ): void;
   forEach( iteratee: SlidesIteratee, excludeClones?: boolean ): void;
   filter( matcher: SlideMatcher ): SlideComponent[];
-  rule( prop: string, value: string | number, useContainer?: boolean ): void
+  style( prop: string, value: string | number, useContainer?: boolean ): void
   getLength( excludeClones?: boolean ): number;
   isEnough(): boolean;
 }
@@ -88,6 +88,9 @@ export function Slides( Splide: Splide, Components: Components, options: Options
   function mount(): void {
     init();
     on( EVENT_REFRESH, refresh );
+    on( [ EVENT_MOUNTED, EVENT_REFRESH ], () => {
+      Slides.sort( ( Slide1, Slide2 ) => Slide1.index - Slide2.index );
+    } );
   }
 
   /**
@@ -230,8 +233,8 @@ export function Slides( Splide: Splide, Components: Components, options: Options
    * @param value        - A CSS value to add.
    * @param useContainer - Optional. Determines whether to apply the rule to the container or not.
    */
-  function rule( prop: string, value: string | number, useContainer?: boolean ): void {
-    forEach( Slide => { Slide.rule( prop, value, useContainer ) } );
+  function style( prop: string, value: string | number, useContainer?: boolean ): void {
+    forEach( Slide => { Slide.style( prop, value, useContainer ) } );
   }
 
   /**
@@ -288,7 +291,7 @@ export function Slides( Splide: Splide, Components: Components, options: Options
     remove,
     forEach,
     filter,
-    rule,
+    style,
     getLength,
     isEnough,
   };

+ 0 - 99
src/js/components/Style/Style.ts

@@ -1,99 +0,0 @@
-import { BaseComponent } from '../../types';
-import { create, find, isHTMLElement, remove } from '../../utils';
-
-
-/**
- * The interface for the Style component.
- *
- * @since 3.0.0
- */
-export interface StyleComponent extends BaseComponent {
-  rule( selector: string, prop: string, value: string | number ): void;
-  ruleBy( target: string | HTMLElement, prop: string, value: string | number ): void;
-}
-
-/**
- * The component for managing styles of the slider.
- *
- * @since 3.0.0
- *
- * @return A Style component object.
- */
-export function Style(): StyleComponent {
-  /**
-   * The style element for the slider.
-   */
-  let style: HTMLStyleElement;
-
-  /**
-   * The CSSStyleSheet object of the created style element.
-   */
-  let sheet: CSSStyleSheet;
-
-  /**
-   * Called when the component is mounted.
-   */
-  function mount(): void {
-    style = create( 'style', {}, document.head );
-    sheet = style.sheet;
-  }
-
-  /**
-   * Destroys the component.
-   */
-  function destroy(): void {
-    remove( style );
-    sheet = null;
-  }
-
-  /**
-   * Registers the style for the selector.
-   *
-   * @param selector - A selector string.
-   * @param prop     - A CSS property, accepting the camel case.
-   * @param value    - A CSS value.
-   */
-  function rule( selector: string, prop: string, value: string | number ): void {
-    const { cssRules } = sheet;
-    const cssRule = find( cssRules, cssRule => isCSSStyleRule( cssRule ) && cssRule.selectorText === selector )
-      || cssRules[ sheet.insertRule( `${ selector }{}`, 0 ) ];
-
-    if ( isCSSStyleRule( cssRule ) ) {
-      const { style } = cssRule;
-      value = `${ value }`;
-
-      if ( style[ prop ] !== value ) {
-        style[ prop ] = value;
-      }
-    }
-  }
-
-  /**
-   * Registers the style by the element or the ID.
-   *
-   * @param target - A target element or ID.
-   * @param prop   - A CSS property, accepting the camel case.
-   * @param value  - A CSS value.
-   */
-  function ruleBy( target: string | HTMLElement, prop: string, value: string | number ): void {
-    rule( `#${ isHTMLElement( target ) ? target.id : target }`, prop, value );
-  }
-
-  /**
-   * Checks if the provided rule is a CSSStyleRule instance or not.
-   *
-   * @param cssRule - An instance to check.
-   *
-   * @return `true` if the cssRule is an instance of CSSStyleRule, or otherwise `false`.
-   */
-  function isCSSStyleRule( cssRule: CSSRule ): cssRule is CSSStyleRule {
-    return cssRule instanceof CSSStyleRule;
-  }
-
-  return {
-    mount,
-    destroy,
-    rule,
-    ruleBy,
-  };
-}

+ 0 - 59
src/js/components/Style/test/general.test.ts

@@ -1,59 +0,0 @@
-import { findRuleBy, init } from '../../../test';
-
-
-describe( 'Style', () => {
-  test( 'can create a style element and append it to the head element.', () => {
-    const splide = init( { width: 100 } );
-    const style  = document.head.lastElementChild;
-
-    expect( style instanceof HTMLStyleElement ).toBe( true );
-
-    if ( style instanceof HTMLStyleElement ) {
-      const { cssRules } = style.sheet;
-
-      const rootRule = Array.prototype.find.call( cssRules, ( cssRule: CSSStyleRule ) => {
-        return cssRule.selectorText === `#${ splide.root.id }`;
-      } );
-
-      expect( rootRule ).not.toBeUndefined();
-      expect( rootRule.style.maxWidth ).toBe( '100px' );
-    }
-
-    splide.destroy();
-  } );
-
-  test( 'can add a style by a selector.', () => {
-    const splide = init();
-    const { rule } = splide.Components.Style;
-
-    rule( `#${ splide.root.id }`, 'opacity', 0.5 );
-
-    const rules = findRuleBy( splide.root );
-
-    expect( rules.style.opacity ).toBe( '0.5' );
-
-    splide.destroy();
-  } );
-
-  test( 'can add a style by an element.', () => {
-    const splide = init();
-    const { ruleBy } = splide.Components.Style;
-
-    ruleBy( splide.root, 'opacity', 0.4 );
-
-    const rules = findRuleBy( splide.root );
-
-    expect( rules.style.opacity ).toBe( '0.4' );
-
-    splide.destroy();
-  } );
-
-  test( 'can remove the style element on destroy.', () => {
-    const splide = init();
-
-    expect( document.head.lastElementChild instanceof HTMLStyleElement ).toBe( true );
-
-    splide.destroy();
-    expect( document.head.lastElementChild ).toBeNull();
-  } );
-} );

+ 1 - 2
src/js/components/index.ts

@@ -1,10 +1,9 @@
 export { Options }    from './Options/Options';
 export { Direction }  from './Direction/Direction';
 export { Elements }   from './Elements/Elements';
-export { Style }      from './Style/Style';
 export { Slides }     from './Slides/Slides';
-export { Clones }     from './Clones/Clones';
 export { Layout }     from './Layout/Layout';
+export { Clones }     from './Clones/Clones';
 export { Move }       from './Move/Move';
 export { Controller } from './Controller/Controller';
 export { Arrows }     from './Arrows/Arrows';

+ 1 - 1
src/js/constants/defaults.ts

@@ -20,7 +20,7 @@ export const DEFAULTS: Options = {
   pauseOnHover     : true,
   pauseOnFocus     : true,
   resetProgress    : true,
-  easing           : 'cubic-bezier(.42,.65,.27,.99)',
+  easing           : 'cubic-bezier(0.25, 1, 0.5, 1)',
   drag             : true,
   direction        : 'ltr',
   slideFocus       : true,

+ 2 - 2
src/js/constructors/EventBus/test/key.test.ts

@@ -80,7 +80,7 @@ describe( 'EventBus', () => {
     event.emit( 'mounted' );
 
     expect( callback1 ).toHaveBeenCalledTimes( 1 );
-    expect( callback2 ).not.toHaveBeenCalled()
-    expect( callback3 ).not.toHaveBeenCalled()
+    expect( callback2 ).not.toHaveBeenCalled();
+    expect( callback3 ).not.toHaveBeenCalled();
   } );
 } );

+ 3 - 3
src/js/test/assets/css/styles.css

@@ -34,9 +34,9 @@ button:focus {
   border: 2px solid deepskyblue;
 }
 
-.splide__slide:focus, .splide__arrow:focus, .splide__pagination__page:focus {
-  border: 2px solid tomato !important;
-}
+/*.splide__slide:focus, .splide__arrow:focus, .splide__pagination__page:focus {*/
+/*  border: 2px solid tomato !important;*/
+/*}*/
 
 .splide__pagination__page.is-active {
   background: deepskyblue;

+ 0 - 1
src/js/test/php/examples/breakpoints.php

@@ -20,7 +20,6 @@ $settings = get_settings();
     document.addEventListener( 'DOMContentLoaded', function () {
       var splide = new Splide( '#splide01', {
         perPage    : 3,
-        // gap        : '2rem',
         arrows     : false,
         mediaQuery : 'min',
         breakpoints: {

+ 23 - 19
src/js/test/php/examples/default.php

@@ -22,12 +22,16 @@ $settings = get_settings();
         type             : 'loop',
         perPage          : 3,
         gap              : '1.5rem',
-        // height           : 400,
+        // speed: 600,
+        cover: true,
+        height           : 400,
         // waitForTransition: false,
         // direction        : 'ltr',
         // drag      : true,
-        pagination: false,
-        arrows: false,
+        // pagination: false,
+        // arrows: false,
+        useScroll: true,
+        // focus: 'center',1
         classes: {
           arrows: 'splide__arrows splide__test',
         },
@@ -41,21 +45,21 @@ $settings = get_settings();
         },
       } );
 
-      splide.on( 'moved', () => {
-        console.log( 'moved' );
-      } );
-
-      splide.on( 'visible', Slide => {
-        console.log( 'visible', Slide.index );
-      } );
-
-      splide.on( 'hidden', Slide => {
-        console.log( 'hidden', Slide.index );
-      } );
-
-      splide.on( 'click', () => {
-        console.log( 'click' );
-      } );
+      // splide.on( 'moved', () => {
+      //   console.log( 'moved' );
+      // } );
+      //
+      // splide.on( 'visible', Slide => {
+      //   console.log( 'visible', Slide.index );
+      // } );
+      //
+      // splide.on( 'hidden', Slide => {
+      //   console.log( 'hidden', Slide.index );
+      // } );
+      //
+      // splide.on( 'click', () => {
+      //   console.log( 'click' );
+      // } );
 
       splide.mount();
     } );
@@ -68,7 +72,7 @@ $settings = get_settings();
   </style>
 </head>
 <body>
-
+2
 <?php render(); ?>
 
 <pre></pre>

+ 3 - 2
src/js/test/php/examples/sync.php

@@ -21,17 +21,18 @@ $settings = get_settings();
         type       : 'loop',
         heightRatio: 0.3,
         perPage    : 2,
-        cover      : true,
+        // cover      : true,
       } );
 
       var splide02 = new Splide( '#splide02', {
-        width       : 600,
+        // width       : 600,
         fixedWidth  : 100,
         fixedHeight : 56,
         gap         : '.7em',
         isNavigation: true,
         focus       : 'center',
         pagination  : false,
+        type        : 'loop',
       } );
 
       var splide03 = new Splide( '#splide03', {

+ 0 - 26
src/js/test/utils/utils.ts

@@ -181,29 +181,3 @@ export function wait( duration: number ): Promise<void> {
     setTimeout( resolve, duration );
   } );
 }
-
-/**
- * Finds the CSSRule object.
- *
- * @param selector - A selector to find.
- *
- * @return A found CSSRule object.
- */
-export function findRule( selector: string ): CSSStyleRule {
-  const cssRules = document.styleSheets[ 0 ].cssRules;
-
-  return Array.prototype.find.call( cssRules, ( rule: CSSRule ) => {
-    return rule instanceof CSSStyleRule && rule.selectorText === selector;
-  } );
-}
-
-/**
- * Finds the CSSRule object by ID.
- *
- * @param target - The element or ID.
- *
- * @return A found CSSRule object.
- */
-export function findRuleBy( target: string | HTMLElement ): CSSStyleRule {
-  return findRule( `#${ target instanceof HTMLElement ? target.id : target }` );
-}

+ 4 - 7
src/js/transitions/Fade/Fade.ts

@@ -2,7 +2,7 @@ import { EVENT_MOUNTED, EVENT_REFRESH } from '../../constants/events';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { Components, Options, TransitionComponent } from '../../types';
-import { nextTick, noop, rect, unit } from '../../utils';
+import { nextTick, noop, rect, unit, style } from '../../utils';
 
 
 /**
@@ -18,7 +18,6 @@ import { nextTick, noop, rect, unit } from '../../utils';
  */
 export function Fade( Splide: Splide, Components: Components, options: Options ): TransitionComponent {
   const { on } = EventInterface( Splide );
-  const { ruleBy } = Components.Style;
 
   /**
    * Called when the component is mounted.
@@ -27,9 +26,7 @@ export function Fade( Splide: Splide, Components: Components, options: Options )
   function mount(): void {
     on( [ EVENT_MOUNTED, EVENT_REFRESH ], () => {
       nextTick( () => {
-        Components.Slides.forEach( Slide => {
-          ruleBy( Slide.slide, 'transition', `opacity ${ options.speed }ms ${ options.easing }` );
-        } );
+        Components.Slides.style( 'transition', `opacity ${ options.speed }ms ${ options.easing }` );
       } );
     } );
   }
@@ -43,11 +40,11 @@ export function Fade( Splide: Splide, Components: Components, options: Options )
    */
   function start( index: number, done: () => void ): void {
     const { track } = Components.Elements;
-    ruleBy( track, 'height', unit( rect( track ).height ) );
+    style( track, 'height', unit( rect( track ).height ) );
 
     nextTick( () => {
       done();
-      ruleBy( track, 'height', '' );
+      style( track, 'height', '' );
     } );
   }
 

+ 2 - 2
src/js/transitions/Slide/Slide.ts

@@ -2,7 +2,7 @@ import { SLIDE } from '../../constants/types';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { Components, Options, TransitionComponent } from '../../types';
-import { abs } from '../../utils';
+import { abs, style } from '../../utils';
 
 
 /**
@@ -93,7 +93,7 @@ export function Slide( Splide: Splide, Components: Components, options: Options
    * @param transition - A transition CSS value.
    */
   function apply( transition: string ): void {
-    Components.Style.ruleBy( list, 'transition', transition );
+    style( list, 'transition', transition );
   }
 
   return {

+ 5 - 0
src/js/types/options.ts

@@ -147,6 +147,11 @@ export interface Options extends ResponsiveOptions {
    */
   focusableNodes?: string,
 
+  /**
+   * Determines whether to use the Transition component or not.
+   */
+  useScroll?: boolean;
+
   /**
    * Options for specific breakpoints.
    *

+ 1 - 1
src/js/utils/dom/display/display.ts

@@ -8,5 +8,5 @@ import { style } from '../style/style';
  * @param display - A new `display` value.
  */
 export function display( elm: HTMLElement, display: string ): void {
-  style( elm, { display } );
+  style( elm, 'display', display );
 }

+ 10 - 2
src/js/utils/dom/style/style.test.ts

@@ -2,12 +2,20 @@ import { style } from './style';
 
 
 describe( 'styles', () => {
-  test( 'can set inline styles by an object literal.', () => {
+  test( 'can set an inline style', () => {
     const div = document.createElement( 'div' );
-    style( div, { color: 'red', backgroundColor: 'white', fontSize: '1rem' } );
+    style( div, 'color', 'red' );
+    style( div, 'backgroundColor', 'white' );
+    style( div, 'fontSize', '1rem' );
 
     expect( div.style.color ).toBe( 'red' );
     expect( div.style.backgroundColor ).toBe( 'white' );
     expect( div.style.fontSize ).toBe( '1rem' );
   } );
+
+  test( 'can return a computed style', () => {
+    const div = document.createElement( 'div' );
+    div.style.color = 'red';
+    expect( style( div, 'color' ) ).toBe( 'red' );
+  } );
 } );

+ 26 - 28
src/js/utils/dom/style/style.ts

@@ -1,47 +1,45 @@
-import { forOwn } from '../../object';
-import { isNull, isString } from '../../type/type';
+import { isNull, isUndefined } from '../../type/type';
 
 
-/**
- * The union for CSS style properties, such as "padding", "fontSize", etc.
- *
- * @since 0.1.0
- */
-export type CSSStyleProperties = Exclude<keyof CSSStyleDeclaration, number>;
-
-export function style(
-  elm: HTMLElement,
-  styles: Record<string, string | number>
-): void;
-
-export function style<K extends CSSStyleProperties>(
+export function style<K extends keyof CSSStyleDeclaration>(
   elm: HTMLElement,
-  styles: K
+  prop: K,
 ): CSSStyleDeclaration[ K ];
 
 export function style(
   elm: HTMLElement,
-  styles: string
+  prop: string,
 ): string;
 
+export function style(
+  elm: HTMLElement,
+  prop: string,
+  value: string | number
+): void;
+
 
 /**
  * Applies inline styles to the provided element by an object literal.
  *
- * @param elm    - An element to apply styles to.
- * @param styles - An object literal with styles.
+ * @param elm   - An element to apply styles to.
+ * @param prop  - An object literal with styles or a property name.
+ * @param value - A value to set.
  */
-export function style<K extends CSSStyleProperties>(
+export function style(
   elm: HTMLElement,
-  styles: Record<string, string | number> | K
-): CSSStyleDeclaration[ K ] | string | void {
-  if ( isString( styles ) ) {
-    return getComputedStyle( elm )[ styles ];
+  prop: string,
+  value?: string | number
+): string | void {
+  if ( isUndefined( value ) ) {
+    return getComputedStyle( elm )[ prop ];
   }
 
-  forOwn( styles, ( value, key ) => {
-    if ( ! isNull( value ) ) {
-      elm.style[ key ] = `${ value }`;
+  if ( ! isNull( value ) ) {
+    const { style } = elm;
+    value = `${ value }`;
+
+    if ( style[ prop ] !== value ) {
+      style[ prop ] = value;
     }
-  } );
+  }
 }

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