@evermade/overflow-slider 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/.nvmrc +1 -1
  2. package/README.md +17 -3
  3. package/dist/core/overflow-slider.esm.js +2 -0
  4. package/dist/core/overflow-slider.min.js +1 -1
  5. package/dist/core/slider.esm.js +159 -9
  6. package/dist/core/slider.min.js +1 -1
  7. package/dist/overflow-slider.css +1 -1
  8. package/dist/plugins/dots/dots/index.esm.js +21 -22
  9. package/dist/plugins/dots/dots/index.min.js +1 -1
  10. package/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +30 -3
  11. package/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -1
  12. package/dist/plugins/fade/fade/index.esm.js +81 -0
  13. package/dist/plugins/fade/fade/index.min.js +1 -0
  14. package/dist/plugins/full-width/full-width/index.esm.js +1 -0
  15. package/dist/plugins/full-width/full-width/index.min.js +1 -1
  16. package/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +0 -2
  17. package/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -1
  18. package/dist/plugins/thumbnails/thumbnails/index.esm.js +2 -1
  19. package/dist/plugins/thumbnails/thumbnails/index.min.js +1 -1
  20. package/docs/assets/demo.css +16 -0
  21. package/docs/assets/demo.js +44 -7
  22. package/docs/dist/core/overflow-slider.esm.js +2 -0
  23. package/docs/dist/core/overflow-slider.min.js +1 -1
  24. package/docs/dist/core/slider.esm.js +159 -9
  25. package/docs/dist/core/slider.min.js +1 -1
  26. package/docs/dist/overflow-slider.css +1 -1
  27. package/docs/dist/plugins/dots/dots/index.esm.js +21 -22
  28. package/docs/dist/plugins/dots/dots/index.min.js +1 -1
  29. package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +30 -3
  30. package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -1
  31. package/docs/dist/plugins/fade/fade/index.esm.js +81 -0
  32. package/docs/dist/plugins/fade/fade/index.min.js +1 -0
  33. package/docs/dist/plugins/full-width/full-width/index.esm.js +1 -0
  34. package/docs/dist/plugins/full-width/full-width/index.min.js +1 -1
  35. package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +0 -2
  36. package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -1
  37. package/docs/dist/plugins/thumbnails/thumbnails/index.esm.js +2 -1
  38. package/docs/dist/plugins/thumbnails/thumbnails/index.min.js +1 -1
  39. package/docs/index.html +39 -7
  40. package/package.json +7 -2
  41. package/src/core/overflow-slider.ts +2 -0
  42. package/src/core/slider.ts +176 -14
  43. package/src/core/types.ts +31 -1
  44. package/src/overflow-slider.scss +2 -1
  45. package/src/plugins/dots/index.ts +21 -23
  46. package/src/plugins/drag-scrolling/index.ts +34 -5
  47. package/src/plugins/fade/index.ts +102 -0
  48. package/src/plugins/fade/styles.scss +27 -0
  49. package/src/plugins/full-width/index.ts +1 -0
  50. package/src/plugins/scroll-indicator/index.ts +0 -2
  51. package/src/plugins/thumbnails/index.ts +2 -1
package/.nvmrc CHANGED
@@ -1 +1 @@
1
- v16.16.0
1
+ v16.16.0
package/README.md CHANGED
@@ -94,7 +94,7 @@ const slider = new OverflowSlider(
94
94
  You can import base styles from the library to get started. The base styles include basic styles for the slider and some plugins.
95
95
 
96
96
  ```scss
97
- @import "@evermade/overflow-slider/dist/overflow-slider.css";
97
+ @import "@evermade/overflow-slider/style.css";
98
98
  ```
99
99
 
100
100
  You can use the CSS variables to override some values easily.
@@ -127,14 +127,28 @@ Auto-play is not supported at the moment but can probably be implemented as a pl
127
127
 
128
128
  ## To-do
129
129
 
130
- * Make drag scrolling snapping smooth (might be browser limitation)
131
- * Rethink dot amount calculation
132
130
  * Maybe split styles to separate files for plugins (but keep offering bundle as well)
133
131
  * Maybe add plugin that adds class for visible slides
134
132
  * Document all plugins and their parameters here
135
133
 
136
134
  ## Changelog
137
135
 
136
+ ### 3.0.0
137
+
138
+ * Breaking: Change dot plugin to calculate dots based on slides instead of container width "pages"
139
+ * Add: FadePlugin to hint that there are more slides to scroll to
140
+ * Add: Scroll snap emulation method
141
+ * Add: Scroll snap emulation for DragScrollingPlugin
142
+ * Add: Hooks for different types of scrolling (any, native, programmatic)
143
+ * Add: Hooks for different states of scrolling (start, scroll, end) for above types
144
+ * Refactor: Scroll snapping exceptions to be handled by the core slider
145
+ * Fix: Enhance performance by hooking some plugins only when scrolling has ended
146
+ * Fix: Full width alignment to take into account the container offset
147
+
148
+ ### 2.0.2
149
+
150
+ * Fix: Import style.css from correct path
151
+
138
152
  ### 2.0.1
139
153
 
140
154
  * Fix: Smooth scrolling for moveToSlide method
@@ -10,6 +10,8 @@ function OverflowSlider(container, options, plugins) {
10
10
  scrollBehavior: "smooth",
11
11
  scrollStrategy: "fullSlide",
12
12
  slidesSelector: ":scope > *",
13
+ emulateScrollSnap: false,
14
+ emulateScrollSnapMaxThreshold: 64,
13
15
  };
14
16
  const sliderOptions = Object.assign(Object.assign({}, defaults), options);
15
17
  // disable smooth scrolling if user prefers reduced motion
@@ -1 +1 @@
1
- import e from"./slider.min.js";function o(o,r,t){try{if(!(o instanceof Element))throw new Error("Container must be HTML element, found "+typeof o);const s={scrollBehavior:"smooth",scrollStrategy:"fullSlide",slidesSelector:":scope > *"},n=Object.assign(Object.assign({},s),r);return window.matchMedia("(prefers-reduced-motion: reduce)").matches&&(n.scrollBehavior="auto"),e(o,n,t)}catch(e){console.error(e)}}export{o as default};
1
+ import e from"./slider.min.js";function o(o,r,t){try{if(!(o instanceof Element))throw new Error("Container must be HTML element, found "+typeof o);const l={scrollBehavior:"smooth",scrollStrategy:"fullSlide",slidesSelector:":scope > *",emulateScrollSnap:!1,emulateScrollSnapMaxThreshold:64},s=Object.assign(Object.assign({},l),r);return window.matchMedia("(prefers-reduced-motion: reduce)").matches&&(s.scrollBehavior="auto"),e(o,s,t)}catch(e){console.error(e)}}export{o as default};
@@ -69,7 +69,87 @@ function Slider(container, options, plugins) {
69
69
  const resizeObserver = new ResizeObserver(() => slider.emit('containerSizeChanged'));
70
70
  resizeObserver.observe(slider.container);
71
71
  // scroll event with debouncing
72
- slider.container.addEventListener('scroll', () => slider.emit('scroll'));
72
+ let scrollTimeout;
73
+ let nativeScrollTimeout;
74
+ let programmaticScrollTimeout;
75
+ let scrollLeft = slider.container.scrollLeft;
76
+ let nativeScrollLeft = slider.container.scrollLeft;
77
+ let programmaticScrollLeft = slider.container.scrollLeft;
78
+ let isScrolling = false;
79
+ let isUserScrolling = false;
80
+ let isProgrammaticScrolling = false;
81
+ // any scroll
82
+ slider.container.addEventListener('scroll', () => {
83
+ const newScrollLeft = slider.container.scrollLeft;
84
+ if (scrollLeft !== newScrollLeft) {
85
+ if (!isScrolling) {
86
+ isScrolling = true;
87
+ slider.emit('scrollStart');
88
+ }
89
+ scrollLeft = newScrollLeft;
90
+ clearTimeout(scrollTimeout);
91
+ scrollTimeout = setTimeout(() => {
92
+ isScrolling = false;
93
+ slider.emit('scrollEnd');
94
+ }, 50);
95
+ slider.emit('scroll');
96
+ }
97
+ // keep up nativeScrolling to take into account scroll-snap
98
+ if (isUserScrolling) {
99
+ nativeScrollHandler();
100
+ }
101
+ });
102
+ // user initted scroll (touchmove, mouse wheel, etc.)
103
+ const nativeScrollHandler = () => {
104
+ const newScrollLeft = slider.container.scrollLeft;
105
+ if (nativeScrollLeft !== newScrollLeft && !isProgrammaticScrolling) {
106
+ if (!isUserScrolling) {
107
+ slider.emit('nativeScrollStart');
108
+ isUserScrolling = true;
109
+ }
110
+ slider.emit('nativeScroll');
111
+ nativeScrollLeft = newScrollLeft;
112
+ clearTimeout(nativeScrollTimeout);
113
+ nativeScrollTimeout = setTimeout(() => {
114
+ isUserScrolling = false;
115
+ slider.emit('nativeScrollEnd');
116
+ // update programmaticScrollLeft to match nativeScrollLeft
117
+ // this prevents programmaticScroll triggering with no real change to scrollLeft
118
+ programmaticScrollLeft = nativeScrollLeft;
119
+ }, 50);
120
+ }
121
+ };
122
+ slider.container.addEventListener('touchmove', nativeScrollHandler);
123
+ slider.container.addEventListener('mousewheel', nativeScrollHandler);
124
+ slider.container.addEventListener('wheel', nativeScrollHandler);
125
+ // programmatic scroll (scrollTo, etc.)
126
+ slider.on('programmaticScrollStart', () => {
127
+ isProgrammaticScrolling = true;
128
+ });
129
+ slider.container.addEventListener('scroll', () => {
130
+ const newScrollLeft = slider.container.scrollLeft;
131
+ if (programmaticScrollLeft !== newScrollLeft && !isUserScrolling && isProgrammaticScrolling) {
132
+ programmaticScrollLeft = newScrollLeft;
133
+ clearTimeout(programmaticScrollTimeout);
134
+ programmaticScrollTimeout = setTimeout(() => {
135
+ isProgrammaticScrolling = false;
136
+ slider.emit('programmaticScrollEnd');
137
+ // update nativeScrollLeft to match programmaticScrollLeft
138
+ // this prevents nativeScroll triggering with no real change to scrollLeft
139
+ nativeScrollLeft = programmaticScrollLeft;
140
+ }, 50);
141
+ slider.emit('programmaticScroll');
142
+ }
143
+ });
144
+ // Fix issues on scroll snapping not working on programmatic scroll (it's not smooth)
145
+ // by disabling scroll snap if scrolling is programmatic
146
+ slider.on('programmaticScrollStart', () => {
147
+ slider.container.style.scrollSnapType = 'none';
148
+ });
149
+ // restore scroll snap if user scroll starts
150
+ slider.on('nativeScrollStart', () => {
151
+ slider.container.style.scrollSnapType = '';
152
+ });
73
153
  // Listen for mouse down and touch start events on the document
74
154
  // This handles both mouse clicks and touch interactions
75
155
  let wasInteractedWith = false;
@@ -123,18 +203,14 @@ function Slider(container, options, plugins) {
123
203
  else if (slideStart === 0) {
124
204
  scrollTarget = 0;
125
205
  }
206
+ else {
207
+ scrollTarget = slideStart;
208
+ }
126
209
  if (scrollTarget !== null) {
127
- slider.container.style.scrollSnapType = 'none';
128
- // seems like in order for scroll behavior: smooth to work, we need to wait a bit to disable scrollSnapType
129
210
  setTimeout((scrollTarget) => {
211
+ slider.emit('programmaticScrollStart');
130
212
  slider.container.scrollTo({ left: scrollTarget, behavior: behavior });
131
213
  }, 50, scrollTarget);
132
- setTimeout(() => {
133
- // leave snapping off to fix issues with slide moving back on focus
134
- if (behavior == 'smooth') {
135
- slider.container.style.scrollSnapType = '';
136
- }
137
- }, 500);
138
214
  }
139
215
  }
140
216
  function setActiveSlideIdx() {
@@ -171,6 +247,14 @@ function Slider(container, options, plugins) {
171
247
  }
172
248
  return gapSize;
173
249
  }
250
+ function getLeftOffset() {
251
+ let offset = 0;
252
+ const fullWidthOffset = slider.container.getAttribute('data-full-width-offset');
253
+ if (fullWidthOffset) {
254
+ offset = parseInt(fullWidthOffset);
255
+ }
256
+ return offset;
257
+ }
174
258
  function moveToDirection(direction = "prev") {
175
259
  const scrollStrategy = slider.options.scrollStrategy;
176
260
  const scrollLeft = slider.container.scrollLeft;
@@ -231,10 +315,75 @@ function Slider(container, options, plugins) {
231
315
  }
232
316
  }
233
317
  }
318
+ // add left offset
319
+ const offsettedTargetScrollPosition = targetScrollPosition - getLeftOffset();
320
+ if (offsettedTargetScrollPosition >= 0) {
321
+ targetScrollPosition = offsettedTargetScrollPosition;
322
+ }
323
+ slider.emit('programmaticScrollStart');
234
324
  slider.container.style.scrollBehavior = slider.options.scrollBehavior;
235
325
  slider.container.scrollLeft = targetScrollPosition;
236
326
  setTimeout(() => slider.container.style.scrollBehavior = '', 50);
237
327
  }
328
+ function snapToClosestSlide(direction = "prev") {
329
+ const isMovingForward = direction === 'next';
330
+ const slideReference = [];
331
+ for (let i = 0; i < slider.slides.length; i++) {
332
+ const slide = slider.slides[i];
333
+ const slideWidth = slide.offsetWidth;
334
+ const slideStart = slide.offsetLeft;
335
+ const slideEnd = slideStart + slideWidth;
336
+ const slideMiddle = slideStart + slideWidth / 2;
337
+ const trigger = Math.min(slideMiddle, slideStart + slider.options.emulateScrollSnapMaxThreshold);
338
+ slideReference.push({
339
+ start: slideStart,
340
+ middle: slideMiddle,
341
+ end: slideEnd,
342
+ width: slideWidth,
343
+ trigger: trigger,
344
+ slide: slide,
345
+ });
346
+ }
347
+ let snapTarget = null;
348
+ const scrollPosition = slider.container.scrollLeft;
349
+ if (isMovingForward) {
350
+ for (let i = 0; i < slideReference.length; i++) {
351
+ const item = slideReference[i];
352
+ if (i === 0 && scrollPosition <= item.trigger) {
353
+ snapTarget = 0;
354
+ break;
355
+ }
356
+ if (slider.container.scrollLeft <= item.trigger) {
357
+ snapTarget = item.start;
358
+ break;
359
+ }
360
+ }
361
+ }
362
+ else {
363
+ for (let i = slideReference.length - 1; i >= 0; i--) {
364
+ const item = slideReference[i];
365
+ if (i === slideReference.length - 1 && scrollPosition >= item.trigger) {
366
+ snapTarget = item.start;
367
+ break;
368
+ }
369
+ if (slider.container.scrollLeft >= item.trigger) {
370
+ snapTarget = item.start;
371
+ break;
372
+ }
373
+ }
374
+ }
375
+ if (snapTarget !== null) {
376
+ const offsettedSnapTarget = snapTarget - getLeftOffset();
377
+ if (offsettedSnapTarget >= 0) {
378
+ snapTarget = offsettedSnapTarget;
379
+ }
380
+ const scrollBehavior = slider.options.scrollBehavior || 'smooth';
381
+ slider.container.scrollTo({
382
+ left: snapTarget,
383
+ behavior: scrollBehavior
384
+ });
385
+ }
386
+ }
238
387
  function on(name, cb) {
239
388
  if (!subs[name]) {
240
389
  subs[name] = [];
@@ -257,6 +406,7 @@ function Slider(container, options, plugins) {
257
406
  emit,
258
407
  moveToDirection,
259
408
  moveToSlide,
409
+ snapToClosestSlide,
260
410
  on,
261
411
  options,
262
412
  };
@@ -1 +1 @@
1
- import e from"./details.min.js";import{generateId as t,objectsAreEqual as n}from"./utils.min.js";function i(i,o,l){let r,s={};function a(t=!1){const i=r.details,o=e(r);r.details=o,t||n(i,o)?t&&r.emit("detailsChanged"):r.emit("detailsChanged")}function c(){r.slides=Array.from(r.container.querySelectorAll(r.options.slidesSelector))}function d(){r.container.style.setProperty("--slider-container-width",`${r.details.containerWidth}px`),r.container.style.setProperty("--slider-scrollable-width",`${r.details.scrollableAreaWidth}px`),r.container.style.setProperty("--slider-slides-count",`${r.details.slideCount}`)}function f(){r.container.setAttribute("data-has-overflow",r.details.hasOverflow?"true":"false")}function u(e,t=null){const n=t||r.options.scrollBehavior,i=e.getBoundingClientRect(),o=r.container.getBoundingClientRect(),l=r.container.offsetWidth,s=r.container.scrollLeft,a=i.left-o.left+s,c=a+i.width;let d=null;a<s?d=a:c>s+l?d=c-l:0===a&&(d=0),null!==d&&(r.container.style.scrollSnapType="none",setTimeout((e=>{r.container.scrollTo({left:e,behavior:n})}),50,d),setTimeout((()=>{"smooth"==n&&(r.container.style.scrollSnapType="")}),500))}function h(){const e=r.container.getBoundingClientRect(),t=r.container.scrollLeft,n=r.slides;let i=0;for(let o=0;o<n.length;o++){if(n[o].getBoundingClientRect().left-e.left+t+m()>t){i=o;break}}const o=r.activeSlideIdx;r.activeSlideIdx=i,o!==i&&r.emit("activeSlideChanged")}function m(){let e=0;if(r.slides.length>1){const t=r.slides[0].getBoundingClientRect();e=r.slides[1].getBoundingClientRect().left-t.right}return e}return r={emit:function(e){var t;s&&s[e]&&s[e].forEach((e=>{e(r)}));const n=null===(t=null==r?void 0:r.options)||void 0===t?void 0:t[e];"function"==typeof n&&n(r)},moveToDirection:function(e="prev"){const t=r.options.scrollStrategy,n=r.container.scrollLeft,i=r.container.getBoundingClientRect(),o=r.container.offsetWidth;let l=n;if("prev"===e?l=Math.max(0,n-r.container.offsetWidth):"next"===e&&(l=Math.min(r.container.scrollWidth,n+r.container.offsetWidth)),"fullSlide"===t){let t=null;if(t="prev"===e?Math.max(0,l-m()):Math.min(r.container.scrollWidth,l+m()),"next"===e){let e=!1;for(let o of r.slides){const r=o.getBoundingClientRect(),s=r.left-i.left+n,a=s+r.width;if(s<l&&a>l){t=s,e=!0;break}}e||(t=Math.min(l,r.container.scrollWidth-r.container.offsetWidth)),t&&t>n&&(l=t)}else{let e=!1;for(let l of r.slides){const r=l.getBoundingClientRect(),s=r.left-i.left+n,a=s+r.width;if(s<n&&a>n){t=a-o,e=!0;break}}e||(t=Math.max(0,n-o)),t&&t<n&&(l=t)}}r.container.style.scrollBehavior=r.options.scrollBehavior,r.container.scrollLeft=l,setTimeout((()=>r.container.style.scrollBehavior=""),50)},moveToSlide:function(e){const t=r.slides[e];t&&u(t)},on:function(e,t){s[e]||(s[e]=[]),s[e].push(t)},options:o},function(){r.container=i;let e=i.getAttribute("id");null===e&&(e=t("overflow-slider"),i.setAttribute("id",e)),c(),a(!0),h(),r.on("contentsChanged",(()=>{c(),a(),h()})),r.on("containerSizeChanged",(()=>a()));let n=0;if(r.on("scroll",(()=>{n&&window.cancelAnimationFrame(n),n=window.requestAnimationFrame((()=>{a(),h()}))})),function(){new MutationObserver((()=>r.emit("contentsChanged"))).observe(r.container,{childList:!0});new ResizeObserver((()=>r.emit("containerSizeChanged"))).observe(r.container),r.container.addEventListener("scroll",(()=>r.emit("scroll")));let e=!1;r.container.addEventListener("mousedown",(()=>{e=!0})),r.container.addEventListener("touchstart",(()=>{e=!0}),{passive:!0}),r.container.addEventListener("focusin",(t=>{if(!e){let e=t.target;for(;e.parentElement!==r.container&&e.parentElement;)e=e.parentElement;u(e,"auto")}e=!1}))}(),f(),d(),l)for(const e of l)e(r);r.on("detailsChanged",(()=>{f(),d()})),r.emit("created"),r.container.setAttribute("data-ready","true")}(),r}export{i as default};
1
+ import t from"./details.min.js";import{generateId as e,objectsAreEqual as n}from"./utils.min.js";function o(o,i,l){let r,a={};function s(e=!1){const o=r.details,i=t(r);r.details=i,e||n(o,i)?e&&r.emit("detailsChanged"):r.emit("detailsChanged")}function c(){r.slides=Array.from(r.container.querySelectorAll(r.options.slidesSelector))}function d(){r.container.style.setProperty("--slider-container-width",`${r.details.containerWidth}px`),r.container.style.setProperty("--slider-scrollable-width",`${r.details.scrollableAreaWidth}px`),r.container.style.setProperty("--slider-slides-count",`${r.details.slideCount}`)}function f(){r.container.setAttribute("data-has-overflow",r.details.hasOverflow?"true":"false")}function u(t,e=null){const n=e||r.options.scrollBehavior,o=t.getBoundingClientRect(),i=r.container.getBoundingClientRect(),l=r.container.offsetWidth,a=r.container.scrollLeft,s=o.left-i.left+a,c=s+o.width;let d=null;d=s<a?s:c>a+l?c-l:0===s?0:s,null!==d&&setTimeout((t=>{r.emit("programmaticScrollStart"),r.container.scrollTo({left:t,behavior:n})}),50,d)}function m(){const t=r.container.getBoundingClientRect(),e=r.container.scrollLeft,n=r.slides;let o=0;for(let i=0;i<n.length;i++){if(n[i].getBoundingClientRect().left-t.left+e+h()>e){o=i;break}}const i=r.activeSlideIdx;r.activeSlideIdx=o,i!==o&&r.emit("activeSlideChanged")}function h(){let t=0;if(r.slides.length>1){const e=r.slides[0].getBoundingClientRect();t=r.slides[1].getBoundingClientRect().left-e.right}return t}function g(){let t=0;const e=r.container.getAttribute("data-full-width-offset");return e&&(t=parseInt(e)),t}return r={emit:function(t){var e;a&&a[t]&&a[t].forEach((t=>{t(r)}));const n=null===(e=null==r?void 0:r.options)||void 0===e?void 0:e[t];"function"==typeof n&&n(r)},moveToDirection:function(t="prev"){const e=r.options.scrollStrategy,n=r.container.scrollLeft,o=r.container.getBoundingClientRect(),i=r.container.offsetWidth;let l=n;if("prev"===t?l=Math.max(0,n-r.container.offsetWidth):"next"===t&&(l=Math.min(r.container.scrollWidth,n+r.container.offsetWidth)),"fullSlide"===e){let e=null;if(e="prev"===t?Math.max(0,l-h()):Math.min(r.container.scrollWidth,l+h()),"next"===t){let t=!1;for(let i of r.slides){const r=i.getBoundingClientRect(),a=r.left-o.left+n,s=a+r.width;if(a<l&&s>l){e=a,t=!0;break}}t||(e=Math.min(l,r.container.scrollWidth-r.container.offsetWidth)),e&&e>n&&(l=e)}else{let t=!1;for(let l of r.slides){const r=l.getBoundingClientRect(),a=r.left-o.left+n,s=a+r.width;if(a<n&&s>n){e=s-i,t=!0;break}}t||(e=Math.max(0,n-i)),e&&e<n&&(l=e)}}const a=l-g();a>=0&&(l=a),r.emit("programmaticScrollStart"),r.container.style.scrollBehavior=r.options.scrollBehavior,r.container.scrollLeft=l,setTimeout((()=>r.container.style.scrollBehavior=""),50)},moveToSlide:function(t){const e=r.slides[t];e&&u(e)},snapToClosestSlide:function(t="prev"){const e="next"===t,n=[];for(let t=0;t<r.slides.length;t++){const e=r.slides[t],o=e.offsetWidth,i=e.offsetLeft,l=i+o,a=i+o/2,s=Math.min(a,i+r.options.emulateScrollSnapMaxThreshold);n.push({start:i,middle:a,end:l,width:o,trigger:s,slide:e})}let o=null;const i=r.container.scrollLeft;if(e)for(let t=0;t<n.length;t++){const e=n[t];if(0===t&&i<=e.trigger){o=0;break}if(r.container.scrollLeft<=e.trigger){o=e.start;break}}else for(let t=n.length-1;t>=0;t--){const e=n[t];if(t===n.length-1&&i>=e.trigger){o=e.start;break}if(r.container.scrollLeft>=e.trigger){o=e.start;break}}if(null!==o){const t=o-g();t>=0&&(o=t);const e=r.options.scrollBehavior||"smooth";r.container.scrollTo({left:o,behavior:e})}},on:function(t,e){a[t]||(a[t]=[]),a[t].push(e)},options:i},function(){r.container=o;let t=o.getAttribute("id");null===t&&(t=e("overflow-slider"),o.setAttribute("id",t)),c(),s(!0),m(),r.on("contentsChanged",(()=>{c(),s(),m()})),r.on("containerSizeChanged",(()=>s()));let n=0;if(r.on("scroll",(()=>{n&&window.cancelAnimationFrame(n),n=window.requestAnimationFrame((()=>{s(),m()}))})),function(){new MutationObserver((()=>r.emit("contentsChanged"))).observe(r.container,{childList:!0});let t,e,n;new ResizeObserver((()=>r.emit("containerSizeChanged"))).observe(r.container);let o=r.container.scrollLeft,i=r.container.scrollLeft,l=r.container.scrollLeft,a=!1,s=!1,c=!1;r.container.addEventListener("scroll",(()=>{const e=r.container.scrollLeft;o!==e&&(a||(a=!0,r.emit("scrollStart")),o=e,clearTimeout(t),t=setTimeout((()=>{a=!1,r.emit("scrollEnd")}),50),r.emit("scroll")),s&&d()}));const d=()=>{const t=r.container.scrollLeft;i===t||c||(s||(r.emit("nativeScrollStart"),s=!0),r.emit("nativeScroll"),i=t,clearTimeout(e),e=setTimeout((()=>{s=!1,r.emit("nativeScrollEnd"),l=i}),50))};r.container.addEventListener("touchmove",d),r.container.addEventListener("mousewheel",d),r.container.addEventListener("wheel",d),r.on("programmaticScrollStart",(()=>{c=!0})),r.container.addEventListener("scroll",(()=>{const t=r.container.scrollLeft;l!==t&&!s&&c&&(l=t,clearTimeout(n),n=setTimeout((()=>{c=!1,r.emit("programmaticScrollEnd"),i=l}),50),r.emit("programmaticScroll"))})),r.on("programmaticScrollStart",(()=>{r.container.style.scrollSnapType="none"})),r.on("nativeScrollStart",(()=>{r.container.style.scrollSnapType=""}));let f=!1;r.container.addEventListener("mousedown",(()=>{f=!0})),r.container.addEventListener("touchstart",(()=>{f=!0}),{passive:!0}),r.container.addEventListener("focusin",(t=>{if(!f){let e=t.target;for(;e.parentElement!==r.container&&e.parentElement;)e=e.parentElement;u(e,"auto")}f=!1}))}(),f(),d(),l)for(const t of l)t(r);r.on("detailsChanged",(()=>{f(),d()})),r.emit("created"),r.container.setAttribute("data-ready","true")}(),r}export{o as default};
@@ -1 +1 @@
1
- .overflow-slider{-ms-overflow-style:none;display:grid;grid-auto-flow:column;grid-template-columns:max-content;max-width:-moz-max-content;max-width:max-content;overflow:auto;scrollbar-width:none;width:100%}.overflow-slider::-webkit-scrollbar{display:none}.overflow-slider>*{outline-offset:-2px;scroll-snap-align:start}:root{--overflow-slider-arrows-size:1.5rem;--overflow-slider-arrows-gap:.5rem;--overflow-slider-arrows-inactive-opacity:0.5}.overflow-slider__arrows{display:flex;gap:var(--overflow-slider-arrows-gap)}.overflow-slider__arrows-button{align-items:center;cursor:pointer;display:flex;outline-offset:-2px}.overflow-slider__arrows-button svg{height:var(--overflow-slider-arrows-size);width:var(--overflow-slider-arrows-size)}.overflow-slider__arrows-button[data-has-content=false]{opacity:var(--overflow-slider-arrows-inactive-opacity)}:root{--overflow-slider-dots-gap:0.5rem;--overflow-slider-dot-size:0.75rem;--overflow-slider-dot-inactive-color:rgba(0,0,0,.1);--overflow-slider-dot-active-color:rgba(0,0,0,.8)}.overflow-slider__dots{align-items:center;display:flex;justify-content:center}.overflow-slider__dots ul{display:flex;flex-wrap:wrap;gap:var(--overflow-slider-dots-gap);list-style:none;margin:0;padding:0}.overflow-slider__dots li{line-height:0;margin:0;padding:0}.overflow-slider__dot-item{background:var(--overflow-slider-dot-inactive-color);border-radius:50%;cursor:pointer;height:var(--overflow-slider-dot-size);margin:0;outline-offset:2px;padding:0;position:relative;width:var(--overflow-slider-dot-size)}.overflow-slider__dot-item:after{bottom:calc(var(--overflow-slider-dots-gap)*-1);content:"";display:block;left:calc(var(--overflow-slider-dots-gap)*-1);position:absolute;right:calc(var(--overflow-slider-dots-gap)*-1);top:calc(var(--overflow-slider-dots-gap)*-1)}.overflow-slider__dot-item:focus,.overflow-slider__dot-item:hover,.overflow-slider__dot-item[aria-pressed=true]{background:var(--overflow-slider-dot-active-color)}[data-has-drag-scrolling][data-has-overflow=true]{cursor:grab;-webkit-user-select:none;-moz-user-select:none;user-select:none}:root{--overflow-slider-scroll-indicator-button-height:4px;--overflow-slider-scroll-indicator-padding:1rem;--overflow-slider-scroll-indicator-button-color:rgba(0,0,0,.75);--overflow-slider-scroll-indicator-bar-color:rgba(0,0,0,.25)}.overflow-slider__scroll-indicator{cursor:pointer;outline:0;padding-block:var(--overflow-slider-scroll-indicator-padding);position:relative;width:100%}.overflow-slider__scroll-indicator[data-has-overflow=false]{display:none}.overflow-slider__scroll-indicator:focus-visible .overflow-slider__scroll-indicator-button{outline:2px solid;outline-offset:2px}.overflow-slider__scroll-indicator-bar{background:var(--overflow-slider-scroll-indicator-bar-color);border-radius:3px;height:2px;left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}.overflow-slider__scroll-indicator-button{background:var(--overflow-slider-scroll-indicator-button-color);border-radius:3px;cursor:grab;height:var(--overflow-slider-scroll-indicator-button-height);left:0;position:absolute;top:calc(50% - var(--overflow-slider-scroll-indicator-button-height)/2)}.overflow-slider__scroll-indicator-button:hover,.overflow-slider__scroll-indicator-button[data-is-grabbed=true]{--overflow-slider-scroll-indicator-button-height:6px}.overflow-slider__scroll-indicator-button:after{bottom:calc(var(--overflow-slider-scroll-indicator-padding)*-1);content:"";display:block;position:absolute;top:calc(var(--overflow-slider-scroll-indicator-padding)*-1);width:100%}
1
+ .overflow-slider{-ms-overflow-style:none;display:grid;grid-auto-flow:column;grid-template-columns:max-content;max-width:-moz-max-content;max-width:max-content;overflow:auto;position:relative;scrollbar-width:none;width:100%}.overflow-slider::-webkit-scrollbar{display:none}.overflow-slider>*{outline-offset:-2px;scroll-snap-align:start}:root{--overflow-slider-arrows-size:1.5rem;--overflow-slider-arrows-gap:.5rem;--overflow-slider-arrows-inactive-opacity:0.5}.overflow-slider__arrows{display:flex;gap:var(--overflow-slider-arrows-gap)}.overflow-slider__arrows-button{align-items:center;cursor:pointer;display:flex;outline-offset:-2px}.overflow-slider__arrows-button svg{height:var(--overflow-slider-arrows-size);width:var(--overflow-slider-arrows-size)}.overflow-slider__arrows-button[data-has-content=false]{opacity:var(--overflow-slider-arrows-inactive-opacity)}:root{--overflow-slider-dots-gap:0.5rem;--overflow-slider-dot-size:0.75rem;--overflow-slider-dot-inactive-color:rgba(0,0,0,.1);--overflow-slider-dot-active-color:rgba(0,0,0,.8)}.overflow-slider__dots{align-items:center;display:flex;justify-content:center}.overflow-slider__dots ul{display:flex;flex-wrap:wrap;gap:var(--overflow-slider-dots-gap);list-style:none;margin:0;padding:0}.overflow-slider__dots li{line-height:0;margin:0;padding:0}.overflow-slider__dot-item{background:var(--overflow-slider-dot-inactive-color);border-radius:50%;cursor:pointer;height:var(--overflow-slider-dot-size);margin:0;outline-offset:2px;padding:0;position:relative;width:var(--overflow-slider-dot-size)}.overflow-slider__dot-item:after{bottom:calc(var(--overflow-slider-dots-gap)*-1);content:"";display:block;left:calc(var(--overflow-slider-dots-gap)*-1);position:absolute;right:calc(var(--overflow-slider-dots-gap)*-1);top:calc(var(--overflow-slider-dots-gap)*-1)}.overflow-slider__dot-item:focus,.overflow-slider__dot-item:hover,.overflow-slider__dot-item[aria-pressed=true]{background:var(--overflow-slider-dot-active-color)}:root{--overflow-slider-fade-color:#fff;--overflow-slider-fade-width:3rem}.overflow-slider-fade{height:100%;pointer-events:none;position:absolute;top:0;width:var(--overflow-slider-fade-width);z-index:1}.overflow-slider-fade--start{background:linear-gradient(to right,var(--overflow-slider-fade-color) 0,transparent 100%);left:0}.overflow-slider-fade--end{background:linear-gradient(to left,var(--overflow-slider-fade-color) 0,transparent 100%);right:0}[data-has-drag-scrolling][data-has-overflow=true]{cursor:grab;-webkit-user-select:none;-moz-user-select:none;user-select:none}:root{--overflow-slider-scroll-indicator-button-height:4px;--overflow-slider-scroll-indicator-padding:1rem;--overflow-slider-scroll-indicator-button-color:rgba(0,0,0,.75);--overflow-slider-scroll-indicator-bar-color:rgba(0,0,0,.25)}.overflow-slider__scroll-indicator{cursor:pointer;outline:0;padding-block:var(--overflow-slider-scroll-indicator-padding);position:relative;width:100%}.overflow-slider__scroll-indicator[data-has-overflow=false]{display:none}.overflow-slider__scroll-indicator:focus-visible .overflow-slider__scroll-indicator-button{outline:2px solid;outline-offset:2px}.overflow-slider__scroll-indicator-bar{background:var(--overflow-slider-scroll-indicator-bar-color);border-radius:3px;height:2px;left:0;position:absolute;top:50%;transform:translateY(-50%);width:100%}.overflow-slider__scroll-indicator-button{background:var(--overflow-slider-scroll-indicator-button-color);border-radius:3px;cursor:grab;height:var(--overflow-slider-scroll-indicator-button-height);left:0;position:absolute;top:calc(50% - var(--overflow-slider-scroll-indicator-button-height)/2)}.overflow-slider__scroll-indicator-button:hover,.overflow-slider__scroll-indicator-button[data-is-grabbed=true]{--overflow-slider-scroll-indicator-button-height:6px}.overflow-slider__scroll-indicator-button:after{bottom:calc(var(--overflow-slider-scroll-indicator-padding)*-1);content:"";display:block;position:absolute;top:calc(var(--overflow-slider-scroll-indicator-padding)*-1);width:100%}
@@ -20,8 +20,8 @@ function DotsPlugin(args) {
20
20
  dots.setAttribute('data-has-content', slider.details.hasOverflow.toString());
21
21
  dots.innerHTML = '';
22
22
  const dotsList = document.createElement('ul');
23
- const pages = slider.details.amountOfPages;
24
- const currentPage = slider.details.currentPage;
23
+ const pages = slider.details.slideCount;
24
+ const currentItem = slider.activeSlideIdx;
25
25
  if (pages <= 1) {
26
26
  return;
27
27
  }
@@ -31,23 +31,23 @@ function DotsPlugin(args) {
31
31
  dot.setAttribute('type', 'button');
32
32
  dot.setAttribute('class', options.classNames.dotsItem);
33
33
  dot.setAttribute('aria-label', options.texts.dotDescription.replace('%d', (i + 1).toString()).replace('%d', pages.toString()));
34
- dot.setAttribute('aria-pressed', (i === currentPage).toString());
35
- dot.setAttribute('data-page', (i + 1).toString());
34
+ dot.setAttribute('aria-pressed', (i === currentItem).toString());
35
+ dot.setAttribute('data-item', (i + 1).toString());
36
36
  dotListItem.appendChild(dot);
37
37
  dotsList.appendChild(dotListItem);
38
38
  dot.addEventListener('click', () => activateDot(i + 1));
39
39
  dot.addEventListener('focus', () => pageFocused = i + 1);
40
40
  dot.addEventListener('keydown', (e) => {
41
41
  var _a;
42
- const currentPageItem = dots.querySelector(`[aria-pressed="true"]`);
43
- if (!currentPageItem) {
42
+ const currentItemItem = dots.querySelector(`[aria-pressed="true"]`);
43
+ if (!currentItemItem) {
44
44
  return;
45
45
  }
46
- const currentPage = parseInt((_a = currentPageItem.getAttribute('data-page')) !== null && _a !== void 0 ? _a : '1');
46
+ const currentItem = parseInt((_a = currentItemItem.getAttribute('data-item')) !== null && _a !== void 0 ? _a : '1');
47
47
  if (e.key === 'ArrowLeft') {
48
- const previousPage = currentPage - 1;
48
+ const previousPage = currentItem - 1;
49
49
  if (previousPage > 0) {
50
- const matchingDot = dots.querySelector(`[data-page="${previousPage}"]`);
50
+ const matchingDot = dots.querySelector(`[data-item="${previousPage}"]`);
51
51
  if (matchingDot) {
52
52
  matchingDot.focus();
53
53
  }
@@ -55,9 +55,9 @@ function DotsPlugin(args) {
55
55
  }
56
56
  }
57
57
  if (e.key === 'ArrowRight') {
58
- const nextPage = currentPage + 1;
58
+ const nextPage = currentItem + 1;
59
59
  if (nextPage <= pages) {
60
- const matchingDot = dots.querySelector(`[data-page="${nextPage}"]`);
60
+ const matchingDot = dots.querySelector(`[data-item="${nextPage}"]`);
61
61
  if (matchingDot) {
62
62
  matchingDot.focus();
63
63
  }
@@ -69,19 +69,18 @@ function DotsPlugin(args) {
69
69
  dots.appendChild(dotsList);
70
70
  // return focus to same page after rebuild
71
71
  if (pageFocused) {
72
- const matchingDot = dots.querySelector(`[data-page="${pageFocused}"]`);
72
+ const matchingDot = dots.querySelector(`[data-item="${pageFocused}"]`);
73
73
  if (matchingDot) {
74
74
  matchingDot.focus();
75
75
  }
76
76
  }
77
77
  };
78
- const activateDot = (page) => {
79
- const scrollTargetPosition = slider.details.containerWidth * (page - 1);
80
- slider.container.style.scrollBehavior = slider.options.scrollBehavior;
81
- slider.container.style.scrollSnapType = 'none';
82
- slider.container.scrollLeft = scrollTargetPosition;
83
- slider.container.style.scrollBehavior = '';
84
- slider.container.style.scrollSnapType = '';
78
+ const activateDot = (item) => {
79
+ // const scrollTargetPosition = slider.details.containerWidth * ( page - 1 );
80
+ // slider.container.style.scrollBehavior = slider.options.scrollBehavior;
81
+ // slider.container.scrollLeft = scrollTargetPosition;
82
+ // slider.container.style.scrollBehavior = '';
83
+ slider.moveToSlide(item - 1);
85
84
  };
86
85
  buildDots();
87
86
  if (options.container) {
@@ -90,9 +89,9 @@ function DotsPlugin(args) {
90
89
  else {
91
90
  (_b = slider.container.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(dots, slider.container.nextSibling);
92
91
  }
93
- slider.on('detailsChanged', () => {
94
- buildDots();
95
- });
92
+ slider.on('scrollEnd', buildDots);
93
+ slider.on('contentsChanged', buildDots);
94
+ slider.on('containerSizeChanged', buildDots);
96
95
  };
97
96
  }
98
97
 
@@ -1 +1 @@
1
- const t={dotDescription:"Page %d of %d"},e={dotsContainer:"overflow-slider__dots",dotsItem:"overflow-slider__dot-item"};function n(n){return o=>{var a,s;const r={texts:Object.assign(Object.assign({},t),(null==n?void 0:n.texts)||[]),classNames:Object.assign(Object.assign({},e),(null==n?void 0:n.classNames)||[]),container:null!==(a=null==n?void 0:n.container)&&void 0!==a?a:null},i=document.createElement("div");i.classList.add(r.classNames.dotsContainer);let l=null;const c=()=>{i.setAttribute("data-has-content",o.details.hasOverflow.toString()),i.innerHTML="";const t=document.createElement("ul"),e=o.details.amountOfPages,n=o.details.currentPage;if(!(e<=1)){for(let o=0;o<e;o++){const a=document.createElement("li"),s=document.createElement("button");s.setAttribute("type","button"),s.setAttribute("class",r.classNames.dotsItem),s.setAttribute("aria-label",r.texts.dotDescription.replace("%d",(o+1).toString()).replace("%d",e.toString())),s.setAttribute("aria-pressed",(o===n).toString()),s.setAttribute("data-page",(o+1).toString()),a.appendChild(s),t.appendChild(a),s.addEventListener("click",(()=>d(o+1))),s.addEventListener("focus",(()=>l=o+1)),s.addEventListener("keydown",(t=>{var n;const o=i.querySelector('[aria-pressed="true"]');if(!o)return;const a=parseInt(null!==(n=o.getAttribute("data-page"))&&void 0!==n?n:"1");if("ArrowLeft"===t.key){const t=a-1;if(t>0){const e=i.querySelector(`[data-page="${t}"]`);e&&e.focus(),d(t)}}if("ArrowRight"===t.key){const t=a+1;if(t<=e){const e=i.querySelector(`[data-page="${t}"]`);e&&e.focus(),d(t)}}}))}if(i.appendChild(t),l){const t=i.querySelector(`[data-page="${l}"]`);t&&t.focus()}}},d=t=>{const e=o.details.containerWidth*(t-1);o.container.style.scrollBehavior=o.options.scrollBehavior,o.container.style.scrollSnapType="none",o.container.scrollLeft=e,o.container.style.scrollBehavior="",o.container.style.scrollSnapType=""};c(),r.container?r.container.appendChild(i):null===(s=o.container.parentNode)||void 0===s||s.insertBefore(i,o.container.nextSibling),o.on("detailsChanged",(()=>{c()}))}}export{n as default};
1
+ const t={dotDescription:"Page %d of %d"},e={dotsContainer:"overflow-slider__dots",dotsItem:"overflow-slider__dot-item"};function n(n){return o=>{var i,s;const a={texts:Object.assign(Object.assign({},t),(null==n?void 0:n.texts)||[]),classNames:Object.assign(Object.assign({},e),(null==n?void 0:n.classNames)||[]),container:null!==(i=null==n?void 0:n.container)&&void 0!==i?i:null},r=document.createElement("div");r.classList.add(a.classNames.dotsContainer);let d=null;const l=()=>{r.setAttribute("data-has-content",o.details.hasOverflow.toString()),r.innerHTML="";const t=document.createElement("ul"),e=o.details.slideCount,n=o.activeSlideIdx;if(!(e<=1)){for(let o=0;o<e;o++){const i=document.createElement("li"),s=document.createElement("button");s.setAttribute("type","button"),s.setAttribute("class",a.classNames.dotsItem),s.setAttribute("aria-label",a.texts.dotDescription.replace("%d",(o+1).toString()).replace("%d",e.toString())),s.setAttribute("aria-pressed",(o===n).toString()),s.setAttribute("data-item",(o+1).toString()),i.appendChild(s),t.appendChild(i),s.addEventListener("click",(()=>c(o+1))),s.addEventListener("focus",(()=>d=o+1)),s.addEventListener("keydown",(t=>{var n;const o=r.querySelector('[aria-pressed="true"]');if(!o)return;const i=parseInt(null!==(n=o.getAttribute("data-item"))&&void 0!==n?n:"1");if("ArrowLeft"===t.key){const t=i-1;if(t>0){const e=r.querySelector(`[data-item="${t}"]`);e&&e.focus(),c(t)}}if("ArrowRight"===t.key){const t=i+1;if(t<=e){const e=r.querySelector(`[data-item="${t}"]`);e&&e.focus(),c(t)}}}))}if(r.appendChild(t),d){const t=r.querySelector(`[data-item="${d}"]`);t&&t.focus()}}},c=t=>{o.moveToSlide(t-1)};l(),a.container?a.container.appendChild(r):null===(s=o.container.parentNode)||void 0===s||s.insertBefore(r,o.container.nextSibling),o.on("scrollEnd",l),o.on("contentsChanged",l),o.on("containerSizeChanged",l)}}export{n as default};
@@ -8,9 +8,13 @@ function DragScrollingPlugin(args) {
8
8
  let isMouseDown = false;
9
9
  let startX = 0;
10
10
  let scrollLeft = 0;
11
+ let isMovingForward = false;
12
+ let programmaticScrollStarted = false;
13
+ let mayNeedToSnap = false;
11
14
  // add data attribute to container
12
15
  slider.container.setAttribute('data-has-drag-scrolling', 'true');
13
16
  const mouseDown = (e) => {
17
+ programmaticScrollStarted = false;
14
18
  if (!slider.details.hasOverflow) {
15
19
  return;
16
20
  }
@@ -22,7 +26,6 @@ function DragScrollingPlugin(args) {
22
26
  scrollLeft = slider.container.scrollLeft;
23
27
  // change cursor to grabbing
24
28
  slider.container.style.cursor = 'grabbing';
25
- slider.container.style.scrollSnapType = 'none';
26
29
  slider.container.style.scrollBehavior = 'auto';
27
30
  // prevent focus going to the slides
28
31
  e.preventDefault();
@@ -30,15 +33,26 @@ function DragScrollingPlugin(args) {
30
33
  };
31
34
  const mouseMove = (e) => {
32
35
  if (!slider.details.hasOverflow) {
36
+ programmaticScrollStarted = false;
33
37
  return;
34
38
  }
35
39
  if (!isMouseDown) {
40
+ programmaticScrollStarted = false;
36
41
  return;
37
42
  }
38
43
  e.preventDefault();
44
+ if (!programmaticScrollStarted) {
45
+ programmaticScrollStarted = true;
46
+ slider.emit('programmaticScrollStart');
47
+ }
39
48
  const x = e.pageX - slider.container.offsetLeft;
40
49
  const walk = (x - startX);
41
- slider.container.scrollLeft = scrollLeft - walk;
50
+ const newScrollLeft = scrollLeft - walk;
51
+ mayNeedToSnap = true;
52
+ if (slider.container.scrollLeft !== newScrollLeft) {
53
+ isMovingForward = slider.container.scrollLeft < newScrollLeft;
54
+ }
55
+ slider.container.scrollLeft = newScrollLeft;
42
56
  const absWalk = Math.abs(walk);
43
57
  const slides = slider.container.querySelectorAll(slider.options.slidesSelector);
44
58
  const pointerEvents = absWalk > options.draggedDistanceThatPreventsClick ? 'none' : '';
@@ -48,12 +62,13 @@ function DragScrollingPlugin(args) {
48
62
  };
49
63
  const mouseUp = () => {
50
64
  if (!slider.details.hasOverflow) {
65
+ programmaticScrollStarted = false;
51
66
  return;
52
67
  }
53
68
  isMouseDown = false;
54
69
  slider.container.style.cursor = '';
55
70
  setTimeout(() => {
56
- slider.container.style.scrollSnapType = '';
71
+ programmaticScrollStarted = false;
57
72
  slider.container.style.scrollBehavior = '';
58
73
  const slides = slider.container.querySelectorAll(slider.options.slidesSelector);
59
74
  slides.forEach((slide) => {
@@ -64,6 +79,18 @@ function DragScrollingPlugin(args) {
64
79
  window.addEventListener('mousedown', mouseDown);
65
80
  window.addEventListener('mousemove', mouseMove);
66
81
  window.addEventListener('mouseup', mouseUp);
82
+ // emulate scroll snapping
83
+ if (slider.options.emulateScrollSnap) {
84
+ const snap = () => {
85
+ if (!mayNeedToSnap || isMouseDown) {
86
+ return;
87
+ }
88
+ mayNeedToSnap = false;
89
+ slider.snapToClosestSlide(isMovingForward ? 'next' : 'prev');
90
+ };
91
+ slider.on('programmaticScrollEnd', snap);
92
+ window.addEventListener('mouseup', snap);
93
+ }
67
94
  };
68
95
  }
69
96
 
@@ -1 +1 @@
1
- function e(e){var t;const n=null!==(t=null==e?void 0:e.draggedDistanceThatPreventsClick)&&void 0!==t?t:20;return e=>{let t=!1,o=0,r=0;e.container.setAttribute("data-has-drag-scrolling","true");window.addEventListener("mousedown",(n=>{e.details.hasOverflow&&e.container.contains(n.target)&&(t=!0,o=n.pageX-e.container.offsetLeft,r=e.container.scrollLeft,e.container.style.cursor="grabbing",e.container.style.scrollSnapType="none",e.container.style.scrollBehavior="auto",n.preventDefault(),n.stopPropagation())})),window.addEventListener("mousemove",(a=>{if(!e.details.hasOverflow)return;if(!t)return;a.preventDefault();const s=a.pageX-e.container.offsetLeft-o;e.container.scrollLeft=r-s;const l=Math.abs(s),i=e.container.querySelectorAll(e.options.slidesSelector),c=l>n?"none":"";i.forEach((e=>{e.style.pointerEvents=c}))})),window.addEventListener("mouseup",(()=>{e.details.hasOverflow&&(t=!1,e.container.style.cursor="",setTimeout((()=>{e.container.style.scrollSnapType="",e.container.style.scrollBehavior="";e.container.querySelectorAll(e.options.slidesSelector).forEach((e=>{e.style.pointerEvents=""}))}),50))}))}}export{e as default};
1
+ function e(e){var t;const o=null!==(t=null==e?void 0:e.draggedDistanceThatPreventsClick)&&void 0!==t?t:20;return e=>{let t=!1,n=0,r=0,a=!1,s=!1,i=!1;e.container.setAttribute("data-has-drag-scrolling","true");if(window.addEventListener("mousedown",(o=>{s=!1,e.details.hasOverflow&&e.container.contains(o.target)&&(t=!0,n=o.pageX-e.container.offsetLeft,r=e.container.scrollLeft,e.container.style.cursor="grabbing",e.container.style.scrollBehavior="auto",o.preventDefault(),o.stopPropagation())})),window.addEventListener("mousemove",(l=>{if(!e.details.hasOverflow)return void(s=!1);if(!t)return void(s=!1);l.preventDefault(),s||(s=!0,e.emit("programmaticScrollStart"));const c=l.pageX-e.container.offsetLeft-n,d=r-c;i=!0,e.container.scrollLeft!==d&&(a=e.container.scrollLeft<d),e.container.scrollLeft=d;const u=Math.abs(c),f=e.container.querySelectorAll(e.options.slidesSelector),v=u>o?"none":"";f.forEach((e=>{e.style.pointerEvents=v}))})),window.addEventListener("mouseup",(()=>{e.details.hasOverflow?(t=!1,e.container.style.cursor="",setTimeout((()=>{s=!1,e.container.style.scrollBehavior="";e.container.querySelectorAll(e.options.slidesSelector).forEach((e=>{e.style.pointerEvents=""}))}),50)):s=!1})),e.options.emulateScrollSnap){const o=()=>{i&&!t&&(i=!1,e.snapToClosestSlide(a?"next":"prev"))};e.on("programmaticScrollEnd",o),window.addEventListener("mouseup",o)}}}export{e as default};
@@ -0,0 +1,81 @@
1
+ function FadePlugin(args) {
2
+ return (slider) => {
3
+ var _a, _b, _c;
4
+ const options = {
5
+ classNames: {
6
+ fadeItem: 'overflow-slider-fade',
7
+ fadeItemStart: 'overflow-slider-fade--start',
8
+ fadeItemEnd: 'overflow-slider-fade--end',
9
+ },
10
+ container: (_a = args === null || args === void 0 ? void 0 : args.container) !== null && _a !== void 0 ? _a : null,
11
+ containerStart: (_b = args === null || args === void 0 ? void 0 : args.containerStart) !== null && _b !== void 0 ? _b : null,
12
+ containerEnd: (_c = args === null || args === void 0 ? void 0 : args.containerEnd) !== null && _c !== void 0 ? _c : null,
13
+ };
14
+ const fadeItemStart = document.createElement('div');
15
+ fadeItemStart.classList.add(options.classNames.fadeItem, options.classNames.fadeItemStart);
16
+ fadeItemStart.setAttribute('aria-hidden', 'true');
17
+ fadeItemStart.setAttribute('tabindex', '-1');
18
+ const fadeItemEnd = document.createElement('div');
19
+ fadeItemEnd.classList.add(options.classNames.fadeItem, options.classNames.fadeItemEnd);
20
+ fadeItemEnd.setAttribute('aria-hidden', 'true');
21
+ fadeItemEnd.setAttribute('tabindex', '-1');
22
+ if (options.containerStart) {
23
+ options.containerStart.appendChild(fadeItemStart);
24
+ }
25
+ else if (options.container) {
26
+ options.container.appendChild(fadeItemStart);
27
+ }
28
+ if (options.containerEnd) {
29
+ options.containerEnd.appendChild(fadeItemEnd);
30
+ }
31
+ else if (options.container) {
32
+ options.container.appendChild(fadeItemEnd);
33
+ }
34
+ const hasFadeAtStart = () => {
35
+ return slider.container.scrollLeft > fadeItemStart.offsetWidth;
36
+ };
37
+ const fadeAtStartOpacity = () => {
38
+ const position = slider.container.scrollLeft;
39
+ if (position <= fadeItemStart.offsetWidth) {
40
+ return position / Math.max(fadeItemStart.offsetWidth, 1);
41
+ }
42
+ return 1;
43
+ };
44
+ const hasFadeAtEnd = () => {
45
+ return slider.container.scrollLeft < (slider.container.scrollWidth - slider.container.clientWidth - fadeItemEnd.offsetWidth);
46
+ };
47
+ const fadeAtEndOpacity = () => {
48
+ const position = slider.container.scrollLeft;
49
+ const maxPosition = slider.container.scrollWidth - slider.container.clientWidth;
50
+ const maxFadePosition = maxPosition - fadeItemEnd.offsetWidth;
51
+ if (position >= maxFadePosition) {
52
+ return ((maxFadePosition - position) / Math.max(fadeItemEnd.offsetWidth, 1)) + 1;
53
+ }
54
+ return 1;
55
+ };
56
+ const update = () => {
57
+ fadeItemStart.setAttribute('data-has-fade', hasFadeAtStart().toString());
58
+ fadeItemStart.style.opacity = fadeAtStartOpacity().toString();
59
+ fadeItemEnd.setAttribute('data-has-fade', hasFadeAtEnd().toString());
60
+ fadeItemEnd.style.opacity = fadeAtEndOpacity().toString();
61
+ };
62
+ update();
63
+ slider.on('created', update);
64
+ slider.on('contentsChanged', update);
65
+ slider.on('containerSizeChanged', update);
66
+ slider.on('scrollEnd', update);
67
+ slider.on('scrollStart', update);
68
+ let requestId = 0;
69
+ const debouncedUpdate = () => {
70
+ if (requestId) {
71
+ window.cancelAnimationFrame(requestId);
72
+ }
73
+ requestId = window.requestAnimationFrame(() => {
74
+ update();
75
+ });
76
+ };
77
+ slider.on('scroll', debouncedUpdate);
78
+ };
79
+ }
80
+
81
+ export { FadePlugin as default };
@@ -0,0 +1 @@
1
+ function t(t){return e=>{var n,a,i;const o={classNames:{fadeItem:"overflow-slider-fade",fadeItemStart:"overflow-slider-fade--start",fadeItemEnd:"overflow-slider-fade--end"},container:null!==(n=null==t?void 0:t.container)&&void 0!==n?n:null,containerStart:null!==(a=null==t?void 0:t.containerStart)&&void 0!==a?a:null,containerEnd:null!==(i=null==t?void 0:t.containerEnd)&&void 0!==i?i:null},r=document.createElement("div");r.classList.add(o.classNames.fadeItem,o.classNames.fadeItemStart),r.setAttribute("aria-hidden","true"),r.setAttribute("tabindex","-1");const d=document.createElement("div");d.classList.add(o.classNames.fadeItem,o.classNames.fadeItemEnd),d.setAttribute("aria-hidden","true"),d.setAttribute("tabindex","-1"),o.containerStart?o.containerStart.appendChild(r):o.container&&o.container.appendChild(r),o.containerEnd?o.containerEnd.appendChild(d):o.container&&o.container.appendChild(d);const l=()=>{r.setAttribute("data-has-fade",(e.container.scrollLeft>r.offsetWidth).toString()),r.style.opacity=(()=>{const t=e.container.scrollLeft;return t<=r.offsetWidth?t/Math.max(r.offsetWidth,1):1})().toString(),d.setAttribute("data-has-fade",(e.container.scrollLeft<e.container.scrollWidth-e.container.clientWidth-d.offsetWidth).toString()),d.style.opacity=(()=>{const t=e.container.scrollLeft,n=e.container.scrollWidth-e.container.clientWidth-d.offsetWidth;return t>=n?(n-t)/Math.max(d.offsetWidth,1)+1:1})().toString()};l(),e.on("created",l),e.on("contentsChanged",l),e.on("containerSizeChanged",l),e.on("scrollEnd",l),e.on("scrollStart",l);let s=0;e.on("scroll",(()=>{s&&window.cancelAnimationFrame(s),s=window.requestAnimationFrame((()=>{l()}))}))}}export{t as default};
@@ -21,6 +21,7 @@ function FullWidthPlugin(args) {
21
21
  if (options.addMarginAfter) {
22
22
  lastSlide.style.marginRight = `${marginAmount}px`;
23
23
  }
24
+ slider.container.setAttribute('data-full-width-offset', marginAmount.toString());
24
25
  };
25
26
  update();
26
27
  slider.on('contentsChanged', update);
@@ -1 +1 @@
1
- const n=n=>{var t,e;return null!==(e=null===(t=n.container.parentElement)||void 0===t?void 0:t.offsetWidth)&&void 0!==e?e:window.innerWidth};function t(t){return e=>{var i,r,d;const o={targetWidth:null!==(i=null==t?void 0:t.targetWidth)&&void 0!==i?i:n,addMarginBefore:null===(r=null==t?void 0:t.addMarginBefore)||void 0===r||r,addMarginAfter:null===(d=null==t?void 0:t.addMarginAfter)||void 0===d||d},a=()=>{const n=e.container.querySelectorAll(e.options.slidesSelector);if(!n.length)return;const t=n[0],i=n[n.length-1],r=Math.floor((window.innerWidth-o.targetWidth(e))/2);o.addMarginBefore&&(t.style.marginLeft=`${r}px`),o.addMarginAfter&&(i.style.marginRight=`${r}px`)};a(),e.on("contentsChanged",a),e.on("containerSizeChanged",a)}}export{t as default};
1
+ const t=t=>{var n,e;return null!==(e=null===(n=t.container.parentElement)||void 0===n?void 0:n.offsetWidth)&&void 0!==e?e:window.innerWidth};function n(n){return e=>{var i,r,o;const d={targetWidth:null!==(i=null==n?void 0:n.targetWidth)&&void 0!==i?i:t,addMarginBefore:null===(r=null==n?void 0:n.addMarginBefore)||void 0===r||r,addMarginAfter:null===(o=null==n?void 0:n.addMarginAfter)||void 0===o||o},a=()=>{const t=e.container.querySelectorAll(e.options.slidesSelector);if(!t.length)return;const n=t[0],i=t[t.length-1],r=Math.floor((window.innerWidth-d.targetWidth(e))/2);d.addMarginBefore&&(n.style.marginLeft=`${r}px`),d.addMarginAfter&&(i.style.marginRight=`${r}px`),e.container.setAttribute("data-full-width-offset",r.toString())};a(),e.on("contentsChanged",a),e.on("containerSizeChanged",a)}}export{n as default};