@evermade/overflow-slider 3.0.0 → 3.2.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 (63) hide show
  1. package/README.md +73 -8
  2. package/dist/core/details.esm.js +5 -5
  3. package/dist/core/details.min.js +1 -1
  4. package/dist/core/overflow-slider.esm.js +1 -0
  5. package/dist/core/overflow-slider.min.js +1 -1
  6. package/dist/core/slider.esm.js +113 -44
  7. package/dist/core/slider.min.js +1 -1
  8. package/dist/core/utils.esm.js +15 -1
  9. package/dist/core/utils.min.js +1 -1
  10. package/dist/overflow-slider.css +1 -1
  11. package/dist/plugins/arrows/arrows/index.esm.js +20 -10
  12. package/dist/plugins/arrows/arrows/index.min.js +1 -1
  13. package/dist/plugins/dots/dots/index.esm.js +0 -4
  14. package/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +1 -1
  15. package/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -1
  16. package/dist/plugins/fade/fade/index.esm.js +7 -7
  17. package/dist/plugins/fade/fade/index.min.js +1 -1
  18. package/dist/plugins/full-width/full-width/index.esm.js +7 -2
  19. package/dist/plugins/full-width/full-width/index.min.js +1 -1
  20. package/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +22 -22
  21. package/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -1
  22. package/dist/plugins/thumbnails/thumbnails/index.esm.js +7 -4
  23. package/dist/plugins/thumbnails/thumbnails/index.min.js +1 -1
  24. package/docs/assets/demo.css +11 -1
  25. package/docs/assets/demo.js +38 -12
  26. package/docs/dist/core/details.esm.js +5 -5
  27. package/docs/dist/core/details.min.js +1 -1
  28. package/docs/dist/core/overflow-slider.esm.js +1 -0
  29. package/docs/dist/core/overflow-slider.min.js +1 -1
  30. package/docs/dist/core/slider.esm.js +113 -44
  31. package/docs/dist/core/slider.min.js +1 -1
  32. package/docs/dist/core/utils.esm.js +15 -1
  33. package/docs/dist/core/utils.min.js +1 -1
  34. package/docs/dist/overflow-slider.css +1 -1
  35. package/docs/dist/plugins/arrows/arrows/index.esm.js +20 -10
  36. package/docs/dist/plugins/arrows/arrows/index.min.js +1 -1
  37. package/docs/dist/plugins/dots/dots/index.esm.js +0 -4
  38. package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +1 -1
  39. package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -1
  40. package/docs/dist/plugins/fade/fade/index.esm.js +7 -7
  41. package/docs/dist/plugins/fade/fade/index.min.js +1 -1
  42. package/docs/dist/plugins/full-width/full-width/index.esm.js +7 -2
  43. package/docs/dist/plugins/full-width/full-width/index.min.js +1 -1
  44. package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +22 -22
  45. package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -1
  46. package/docs/dist/plugins/thumbnails/thumbnails/index.esm.js +7 -4
  47. package/docs/dist/plugins/thumbnails/thumbnails/index.min.js +1 -1
  48. package/docs/index-rtl.html +396 -0
  49. package/docs/index.html +1 -1
  50. package/package.json +1 -1
  51. package/src/core/details.ts +5 -5
  52. package/src/core/overflow-slider.ts +1 -0
  53. package/src/core/slider.ts +125 -47
  54. package/src/core/types.ts +5 -0
  55. package/src/core/utils.ts +19 -1
  56. package/src/plugins/arrows/index.ts +20 -10
  57. package/src/plugins/dots/index.ts +0 -4
  58. package/src/plugins/drag-scrolling/index.ts +1 -1
  59. package/src/plugins/fade/index.ts +7 -8
  60. package/src/plugins/fade/styles.scss +10 -0
  61. package/src/plugins/full-width/index.ts +8 -2
  62. package/src/plugins/scroll-indicator/index.ts +62 -64
  63. package/src/plugins/thumbnails/index.ts +7 -5
package/README.md CHANGED
@@ -9,8 +9,9 @@ Overflow Slider aims to be lightweight, mobile-first and accessible. It is desig
9
9
  ## Demos
10
10
 
11
11
  * [Example and demos](https://evermade.github.io/overflow-slider/)
12
+ * [RTL demos](https://evermade.github.io/overflow-slider/index-rtl.html)
12
13
 
13
- ### Usage
14
+ ## Getting started
14
15
 
15
16
  Markup:
16
17
 
@@ -65,7 +66,7 @@ const slider = new OverflowSlider(
65
66
  const slider = new OverflowSlider(
66
67
  document.querySelector( '.slider-container-here' ),
67
68
  {
68
- // options here
69
+ emulateScrollSnap: true,
69
70
  },
70
71
  [
71
72
  ArrowsPlugin({
@@ -101,11 +102,64 @@ You can use the CSS variables to override some values easily.
101
102
 
102
103
  Note that you can easily write styles from scratch if you want to. See source code from `src/overflow-slider.scss` for reference.
103
104
 
105
+ ## Slides per view
106
+
107
+ You control slides per view in CSS. Set gap between slides via `gap` to slider. Slide layout/size is controlled by `width` property. You can use others but `width` is the most stable.
108
+
109
+ ### A) Fixed width
110
+
111
+ Set fixed width for slides: `width: 200px;`. Note you can freely change this with media queries.
112
+
113
+ ### B) Relative width
114
+
115
+ Set relative width for slides: `width: 100vw;`. Note that you cannot use percentages because they are relative to the container and not the viewport.
116
+
117
+ ### C) Variable based width
118
+
119
+ This is most practical approach if you want to make sure exactly 3 slides are visible at all times or so. Or you want to display like 1.5 slides in mobile per view.
120
+
121
+ This is based on getting the container width and dividing it by the number of slides you want to show and subtracting the gap. It's recommended to add SCSS mixin for this in case you are using SCSS.
122
+
123
+ Mixin:
124
+
125
+ ```scss
126
+ @mixin slideWidth($slidesPerView: 3, $gap: var(--slide-gap, 1rem), $containerWidth: var(--slider-container-width, 90vw)) {
127
+ width: calc( ( #{$containerWidth} / #{$slidesPerView} ) - calc( #{$slidesPerView} - 1 ) / #{$slidesPerView} * #{$gap});
128
+ }
129
+ ```
130
+
131
+ Usage:
132
+
133
+ ```scss
134
+ .overflow-slider {
135
+ --gap: 1.5rem;
136
+ gap: var(--gap);
137
+ > * {
138
+ --slidesPerView: 3;
139
+ @include slideWidth(
140
+ var(--slidesPerView),
141
+ var(--gap),
142
+ var(--slider-container-width)
143
+ );
144
+ }
145
+ }
146
+ ```
147
+
148
+ Note that if you are using FullWidthPlugin, you should use container width from `--slider-container-target-width` instead of `--slider-container-width`.
149
+
150
+ ## Plugins
151
+
152
+ TBA
153
+
104
154
  ## Known issues
105
155
 
106
- ### Drag Scrolling and Smoothness
156
+ ### CSS grids and Overflow Slider
157
+
158
+ You can use use Overflow Slider within CSS grid but if you are using `fr` units remember to set them like `minmax(0, 1fr)` instead of just `1fr`. With plain `1fr` the width of columns can be calculated incorrectly by browser.
107
159
 
108
- Scroll snapping doesn't apply smoothly to drag scrolling. It might be browser limitation or some issue with implementation here. Should look into fixing it.
160
+ ### CSS scroll-snap can be buggy
161
+
162
+ If you are using `scroll-snap-type` CSS property, you might encounter some bugs like browser wants to snap to a slide regardless of margins.
109
163
 
110
164
  ## Limitations
111
165
 
@@ -113,10 +167,6 @@ Scroll snapping doesn't apply smoothly to drag scrolling. It might be browser li
113
167
 
114
168
  The library is designed to work with horizontal scrolling. Vertical scrolling is not supported and likely never will because it is not a common use case for sliders.
115
169
 
116
- ### RTL support
117
-
118
- RTL support is not implemented yet. In case need arises it can be implemented but requires changes to the core and plugins.
119
-
120
170
  ### Looping slides
121
171
 
122
172
  Looping slides is not supported and likely never will be. It is a feature that is not very common and it is not very accessible.
@@ -133,6 +183,21 @@ Auto-play is not supported at the moment but can probably be implemented as a pl
133
183
 
134
184
  ## Changelog
135
185
 
186
+ ### 3.2.0
187
+
188
+ * Add: RTL support
189
+ * Add: `--slider-container-target-width` for FullWidthPlugin to allow CSS based on target size
190
+ * Add: Documentation how to set slides per view in CSS
191
+ * Fix: Attach ThumbnailsPlugin to scrollEnd which skips in-between slides when multiple slides are scrolled at once
192
+
193
+ ### 3.1.0
194
+
195
+ * Add: slider.getInclusiveScrollWidth and slider.getInclusiveScrollHeight methods to get widths including outermost childs outermost margins
196
+ * Fix: Lot of bugs related to subpixel widths
197
+ * Fix: Don't run arrow click action if there are no more slides to scroll to
198
+ * Fix: FullWidthPlugin bugs where arrows were not detecting start or end properly (because of child margins not taken into account)
199
+ * Fix: Attach ThumbnailsPlugin to activeSlideChanged which is more appropriate hook
200
+
136
201
  ### 3.0.0
137
202
 
138
203
  * Breaking: Change dot plugin to calculate dots based on slides instead of container width "pages"
@@ -7,17 +7,17 @@ function details(slider) {
7
7
  let scrollableAreaWidth = 0;
8
8
  let amountOfPages = 0;
9
9
  let currentPage = 1;
10
- if (slider.container.scrollWidth > slider.container.clientWidth) {
10
+ if (Math.floor(slider.getInclusiveScrollWidth()) > Math.floor(slider.getInclusiveClientWidth())) {
11
11
  hasOverflow = true;
12
12
  }
13
13
  slideCount = (_a = slider.slides.length) !== null && _a !== void 0 ? _a : 0;
14
14
  containerWidth = slider.container.offsetWidth;
15
- scrollableAreaWidth = slider.container.scrollWidth;
15
+ scrollableAreaWidth = slider.getInclusiveScrollWidth();
16
16
  amountOfPages = Math.ceil(scrollableAreaWidth / containerWidth);
17
- if (slider.container.scrollLeft >= 0) {
18
- currentPage = Math.floor(slider.container.scrollLeft / containerWidth);
17
+ if (Math.floor(slider.getScrollLeft()) >= 0) {
18
+ currentPage = Math.floor(slider.getScrollLeft() / containerWidth);
19
19
  // consider as last page if the scrollLeft + containerWidth is equal to scrollWidth
20
- if (slider.container.scrollLeft + containerWidth === scrollableAreaWidth) {
20
+ if (Math.floor(slider.getScrollLeft() + containerWidth) === Math.floor(scrollableAreaWidth)) {
21
21
  currentPage = amountOfPages - 1;
22
22
  }
23
23
  }
@@ -1 +1 @@
1
- function t(t){var e;let n,l=!1,o=0,r=0,i=0,a=0,c=1;return t.container.scrollWidth>t.container.clientWidth&&(l=!0),o=null!==(e=t.slides.length)&&void 0!==e?e:0,r=t.container.offsetWidth,i=t.container.scrollWidth,a=Math.ceil(i/r),t.container.scrollLeft>=0&&(c=Math.floor(t.container.scrollLeft/r),t.container.scrollLeft+r===i&&(c=a-1)),n={hasOverflow:l,slideCount:o,containerWidth:r,scrollableAreaWidth:i,amountOfPages:a,currentPage:c},n}export{t as default};
1
+ function t(t){var l;let e,o=!1,r=0,a=0,i=0,n=0,f=1;return Math.floor(t.getInclusiveScrollWidth())>Math.floor(t.getInclusiveClientWidth())&&(o=!0),r=null!==(l=t.slides.length)&&void 0!==l?l:0,a=t.container.offsetWidth,i=t.getInclusiveScrollWidth(),n=Math.ceil(i/a),Math.floor(t.getScrollLeft())>=0&&(f=Math.floor(t.getScrollLeft()/a),Math.floor(t.getScrollLeft()+a)===Math.floor(i)&&(f=n-1)),e={hasOverflow:o,slideCount:r,containerWidth:a,scrollableAreaWidth:i,amountOfPages:n,currentPage:f},e}export{t as default};
@@ -12,6 +12,7 @@ function OverflowSlider(container, options, plugins) {
12
12
  slidesSelector: ":scope > *",
13
13
  emulateScrollSnap: false,
14
14
  emulateScrollSnapMaxThreshold: 64,
15
+ rtl: false,
15
16
  };
16
17
  const sliderOptions = Object.assign(Object.assign({}, defaults), options);
17
18
  // 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 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};
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,rtl:!1},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};
@@ -1,5 +1,5 @@
1
1
  import details from './details.esm.js';
2
- import { generateId, objectsAreEqual } from './utils.esm.js';
2
+ import { generateId, objectsAreEqual, getOutermostChildrenEdgeMarginSum } from './utils.esm.js';
3
3
 
4
4
  function Slider(container, options, plugins) {
5
5
  let slider;
@@ -81,7 +81,7 @@ function Slider(container, options, plugins) {
81
81
  // any scroll
82
82
  slider.container.addEventListener('scroll', () => {
83
83
  const newScrollLeft = slider.container.scrollLeft;
84
- if (scrollLeft !== newScrollLeft) {
84
+ if (Math.floor(scrollLeft) !== Math.floor(newScrollLeft)) {
85
85
  if (!isScrolling) {
86
86
  isScrolling = true;
87
87
  slider.emit('scrollStart');
@@ -102,7 +102,7 @@ function Slider(container, options, plugins) {
102
102
  // user initted scroll (touchmove, mouse wheel, etc.)
103
103
  const nativeScrollHandler = () => {
104
104
  const newScrollLeft = slider.container.scrollLeft;
105
- if (nativeScrollLeft !== newScrollLeft && !isProgrammaticScrolling) {
105
+ if (Math.floor(nativeScrollLeft) !== Math.floor(newScrollLeft) && !isProgrammaticScrolling) {
106
106
  if (!isUserScrolling) {
107
107
  slider.emit('nativeScrollStart');
108
108
  isUserScrolling = true;
@@ -128,7 +128,7 @@ function Slider(container, options, plugins) {
128
128
  });
129
129
  slider.container.addEventListener('scroll', () => {
130
130
  const newScrollLeft = slider.container.scrollLeft;
131
- if (programmaticScrollLeft !== newScrollLeft && !isUserScrolling && isProgrammaticScrolling) {
131
+ if (Math.floor(programmaticScrollLeft) !== Math.floor(newScrollLeft) && !isUserScrolling && isProgrammaticScrolling) {
132
132
  programmaticScrollLeft = newScrollLeft;
133
133
  clearTimeout(programmaticScrollTimeout);
134
134
  programmaticScrollTimeout = setTimeout(() => {
@@ -184,6 +184,9 @@ function Slider(container, options, plugins) {
184
184
  }
185
185
  function setDataAttributes() {
186
186
  slider.container.setAttribute('data-has-overflow', slider.details.hasOverflow ? 'true' : 'false');
187
+ if (slider.options.rtl) {
188
+ slider.container.setAttribute('dir', 'rtl');
189
+ }
187
190
  }
188
191
  function ensureSlideIsInView(slide, scrollBehavior = null) {
189
192
  const behavior = scrollBehavior || slider.options.scrollBehavior;
@@ -194,13 +197,13 @@ function Slider(container, options, plugins) {
194
197
  const slideStart = slideRect.left - sliderRect.left + scrollLeft;
195
198
  const slideEnd = slideStart + slideRect.width;
196
199
  let scrollTarget = null;
197
- if (slideStart < scrollLeft) {
200
+ if (Math.floor(slideStart) < Math.floor(scrollLeft)) {
198
201
  scrollTarget = slideStart;
199
202
  }
200
- else if (slideEnd > scrollLeft + containerWidth) {
203
+ else if (Math.floor(slideEnd) > Math.floor(scrollLeft) + Math.floor(containerWidth)) {
201
204
  scrollTarget = slideEnd - containerWidth;
202
205
  }
203
- else if (slideStart === 0) {
206
+ else if (Math.floor(slideStart) === 0) {
204
207
  scrollTarget = 0;
205
208
  }
206
209
  else {
@@ -215,19 +218,56 @@ function Slider(container, options, plugins) {
215
218
  }
216
219
  function setActiveSlideIdx() {
217
220
  const sliderRect = slider.container.getBoundingClientRect();
218
- const scrollLeft = slider.container.scrollLeft;
221
+ const scrollLeft = slider.getScrollLeft();
219
222
  const slides = slider.slides;
220
223
  let activeSlideIdx = 0;
221
- for (let i = 0; i < slides.length; i++) {
222
- const slideRect = slides[i].getBoundingClientRect();
223
- const slideStart = slideRect.left - sliderRect.left + scrollLeft + getGapSize();
224
- if (slideStart > scrollLeft) {
225
- activeSlideIdx = i;
226
- break;
224
+ let scrolledPastLastSlide = false;
225
+ if (slider.options.rtl) {
226
+ const scrolledDistance = slider.getInclusiveScrollWidth() - scrollLeft - slider.getInclusiveClientWidth();
227
+ const slidePositions = [];
228
+ for (let i = slides.length - 1; i >= 0; i--) {
229
+ const slideRect = slides[i].getBoundingClientRect();
230
+ const slideEnd = Math.abs(slideRect.left) - Math.abs(sliderRect.left) + scrolledDistance;
231
+ slidePositions.push({
232
+ slide: slides[i],
233
+ slideEnd: slideEnd,
234
+ });
235
+ }
236
+ let closestSlide = null;
237
+ let closestDistance = null;
238
+ for (let i = 0; i < slidePositions.length; i++) {
239
+ const distance = Math.abs(slidePositions[i].slideEnd - scrolledDistance);
240
+ if (closestDistance === null || distance < closestDistance) {
241
+ closestDistance = distance;
242
+ closestSlide = slidePositions[i].slide;
243
+ }
244
+ }
245
+ if (closestSlide) {
246
+ activeSlideIdx = slides.indexOf(closestSlide);
247
+ }
248
+ else {
249
+ activeSlideIdx = slides.length - 1;
227
250
  }
228
251
  }
252
+ else {
253
+ for (let i = 0; i < slides.length; i++) {
254
+ const slideRect = slides[i].getBoundingClientRect();
255
+ const slideStart = slideRect.left - sliderRect.left + scrollLeft + getGapSize();
256
+ if (Math.floor(slideStart) >= Math.floor(scrollLeft)) {
257
+ activeSlideIdx = i;
258
+ break;
259
+ }
260
+ if (i === slides.length - 1) {
261
+ scrolledPastLastSlide = true;
262
+ }
263
+ }
264
+ }
265
+ if (scrolledPastLastSlide) {
266
+ activeSlideIdx = slides.length - 1;
267
+ }
229
268
  const oldActiveSlideIdx = slider.activeSlideIdx;
230
269
  slider.activeSlideIdx = activeSlideIdx;
270
+ // console.log('activeSlideIdx', activeSlideIdx);
231
271
  if (oldActiveSlideIdx !== activeSlideIdx) {
232
272
  slider.emit('activeSlideChanged');
233
273
  }
@@ -238,12 +278,24 @@ function Slider(container, options, plugins) {
238
278
  ensureSlideIsInView(slide);
239
279
  }
240
280
  }
281
+ function getInclusiveScrollWidth() {
282
+ return slider.container.scrollWidth + getOutermostChildrenEdgeMarginSum(slider.container);
283
+ }
284
+ function getInclusiveClientWidth() {
285
+ return slider.container.clientWidth + getOutermostChildrenEdgeMarginSum(slider.container);
286
+ }
287
+ function getScrollLeft() {
288
+ return slider.options.rtl ? Math.abs(slider.container.scrollLeft) : slider.container.scrollLeft;
289
+ }
290
+ function setScrollLeft(value) {
291
+ slider.container.scrollLeft = slider.options.rtl ? -value : value;
292
+ }
241
293
  function getGapSize() {
242
294
  let gapSize = 0;
243
295
  if (slider.slides.length > 1) {
244
296
  const firstSlideRect = slider.slides[0].getBoundingClientRect();
245
297
  const secondSlideRect = slider.slides[1].getBoundingClientRect();
246
- gapSize = secondSlideRect.left - firstSlideRect.right;
298
+ gapSize = slider.options.rtl ? Math.abs(Math.floor(secondSlideRect.right - firstSlideRect.left)) : Math.floor(secondSlideRect.left - firstSlideRect.right);
247
299
  }
248
300
  return gapSize;
249
301
  }
@@ -253,7 +305,7 @@ function Slider(container, options, plugins) {
253
305
  if (fullWidthOffset) {
254
306
  offset = parseInt(fullWidthOffset);
255
307
  }
256
- return offset;
308
+ return Math.floor(offset);
257
309
  }
258
310
  function moveToDirection(direction = "prev") {
259
311
  const scrollStrategy = slider.options.scrollStrategy;
@@ -261,38 +313,47 @@ function Slider(container, options, plugins) {
261
313
  const sliderRect = slider.container.getBoundingClientRect();
262
314
  const containerWidth = slider.container.offsetWidth;
263
315
  let targetScrollPosition = scrollLeft;
264
- if (direction === 'prev') {
316
+ const realDirection = slider.options.rtl ? (direction === 'prev' ? 'next' : 'prev') : direction;
317
+ if (realDirection === 'prev') {
265
318
  targetScrollPosition = Math.max(0, scrollLeft - slider.container.offsetWidth);
266
319
  }
267
- else if (direction === 'next') {
268
- targetScrollPosition = Math.min(slider.container.scrollWidth, scrollLeft + slider.container.offsetWidth);
320
+ else if (realDirection === 'next') {
321
+ targetScrollPosition = Math.min(slider.getInclusiveScrollWidth(), scrollLeft + slider.container.offsetWidth);
269
322
  }
270
323
  if (scrollStrategy === 'fullSlide') {
271
- let fullSldeTargetScrollPosition = null;
324
+ let fullSlideTargetScrollPosition = null;
272
325
  // extend targetScrollPosition to include gap
273
- if (direction === 'prev') {
274
- fullSldeTargetScrollPosition = Math.max(0, targetScrollPosition - getGapSize());
326
+ if (realDirection === 'prev') {
327
+ fullSlideTargetScrollPosition = Math.max(0, targetScrollPosition - getGapSize());
275
328
  }
276
329
  else {
277
- fullSldeTargetScrollPosition = Math.min(slider.container.scrollWidth, targetScrollPosition + getGapSize());
330
+ fullSlideTargetScrollPosition = Math.min(slider.getInclusiveScrollWidth(), targetScrollPosition + getGapSize());
278
331
  }
279
- if (direction === 'next') {
332
+ if (realDirection === 'next') {
280
333
  let partialSlideFound = false;
281
334
  for (let slide of slider.slides) {
282
335
  const slideRect = slide.getBoundingClientRect();
283
336
  const slideStart = slideRect.left - sliderRect.left + scrollLeft;
284
337
  const slideEnd = slideStart + slideRect.width;
285
- if (slideStart < targetScrollPosition && slideEnd > targetScrollPosition) {
286
- fullSldeTargetScrollPosition = slideStart;
338
+ if (Math.floor(slideStart) < Math.floor(targetScrollPosition) && Math.floor(slideEnd) > Math.floor(targetScrollPosition)) {
339
+ fullSlideTargetScrollPosition = slideStart;
287
340
  partialSlideFound = true;
288
341
  break;
289
342
  }
290
343
  }
291
344
  if (!partialSlideFound) {
292
- fullSldeTargetScrollPosition = Math.min(targetScrollPosition, slider.container.scrollWidth - slider.container.offsetWidth);
345
+ fullSlideTargetScrollPosition = Math.min(targetScrollPosition, slider.getInclusiveScrollWidth() - slider.container.offsetWidth);
293
346
  }
294
- if (fullSldeTargetScrollPosition && fullSldeTargetScrollPosition > scrollLeft) {
295
- targetScrollPosition = fullSldeTargetScrollPosition;
347
+ if (fullSlideTargetScrollPosition) {
348
+ if (Math.floor(fullSlideTargetScrollPosition) > Math.floor(scrollLeft)) {
349
+ // make sure fullSlideTargetScrollPosition is possible considering the container width
350
+ const maxScrollPosition = Math.floor(slider.getInclusiveScrollWidth()) - Math.floor(containerWidth);
351
+ targetScrollPosition = Math.min(fullSlideTargetScrollPosition, maxScrollPosition);
352
+ }
353
+ else {
354
+ // cannot snap to slide, move one page worth of distance
355
+ targetScrollPosition = Math.min(slider.getInclusiveScrollWidth(), scrollLeft + containerWidth);
356
+ }
296
357
  }
297
358
  }
298
359
  else {
@@ -301,23 +362,23 @@ function Slider(container, options, plugins) {
301
362
  const slideRect = slide.getBoundingClientRect();
302
363
  const slideStart = slideRect.left - sliderRect.left + scrollLeft;
303
364
  const slideEnd = slideStart + slideRect.width;
304
- if (slideStart < scrollLeft && slideEnd > scrollLeft) {
305
- fullSldeTargetScrollPosition = slideEnd - containerWidth;
365
+ if (Math.floor(slideStart) < Math.floor(scrollLeft) && Math.floor(slideEnd) > Math.floor(scrollLeft)) {
366
+ fullSlideTargetScrollPosition = slideEnd - containerWidth;
306
367
  partialSlideFound = true;
307
368
  break;
308
369
  }
309
370
  }
310
371
  if (!partialSlideFound) {
311
- fullSldeTargetScrollPosition = Math.max(0, scrollLeft - containerWidth);
372
+ fullSlideTargetScrollPosition = Math.max(0, scrollLeft - containerWidth);
312
373
  }
313
- if (fullSldeTargetScrollPosition && fullSldeTargetScrollPosition < scrollLeft) {
314
- targetScrollPosition = fullSldeTargetScrollPosition;
374
+ if (fullSlideTargetScrollPosition && Math.floor(fullSlideTargetScrollPosition) < Math.floor(scrollLeft)) {
375
+ targetScrollPosition = fullSlideTargetScrollPosition;
315
376
  }
316
377
  }
317
378
  }
318
379
  // add left offset
319
380
  const offsettedTargetScrollPosition = targetScrollPosition - getLeftOffset();
320
- if (offsettedTargetScrollPosition >= 0) {
381
+ if (Math.floor(offsettedTargetScrollPosition) >= 0) {
321
382
  targetScrollPosition = offsettedTargetScrollPosition;
322
383
  }
323
384
  slider.emit('programmaticScrollStart');
@@ -326,12 +387,12 @@ function Slider(container, options, plugins) {
326
387
  setTimeout(() => slider.container.style.scrollBehavior = '', 50);
327
388
  }
328
389
  function snapToClosestSlide(direction = "prev") {
329
- const isMovingForward = direction === 'next';
390
+ const isMovingForward = slider.options.rtl ? direction === 'prev' : direction === 'next';
330
391
  const slideReference = [];
331
392
  for (let i = 0; i < slider.slides.length; i++) {
332
393
  const slide = slider.slides[i];
333
394
  const slideWidth = slide.offsetWidth;
334
- const slideStart = slide.offsetLeft;
395
+ const slideStart = slider.options.rtl ? Math.abs(slide.offsetLeft + slideWidth - slider.details.containerWidth) : slide.offsetLeft;
335
396
  const slideEnd = slideStart + slideWidth;
336
397
  const slideMiddle = slideStart + slideWidth / 2;
337
398
  const trigger = Math.min(slideMiddle, slideStart + slider.options.emulateScrollSnapMaxThreshold);
@@ -342,18 +403,22 @@ function Slider(container, options, plugins) {
342
403
  width: slideWidth,
343
404
  trigger: trigger,
344
405
  slide: slide,
406
+ // debug
407
+ offSetleft: slide.offsetLeft,
408
+ rect: slide.getBoundingClientRect(),
345
409
  });
346
410
  }
411
+ console.log('slideReference', slideReference);
347
412
  let snapTarget = null;
348
- const scrollPosition = slider.container.scrollLeft;
413
+ const scrollPosition = getScrollLeft();
349
414
  if (isMovingForward) {
350
415
  for (let i = 0; i < slideReference.length; i++) {
351
416
  const item = slideReference[i];
352
- if (i === 0 && scrollPosition <= item.trigger) {
417
+ if (i === 0 && Math.floor(scrollPosition) <= Math.floor(item.trigger)) {
353
418
  snapTarget = 0;
354
419
  break;
355
420
  }
356
- if (slider.container.scrollLeft <= item.trigger) {
421
+ if (Math.floor(getScrollLeft()) <= Math.floor(item.trigger)) {
357
422
  snapTarget = item.start;
358
423
  break;
359
424
  }
@@ -362,11 +427,11 @@ function Slider(container, options, plugins) {
362
427
  else {
363
428
  for (let i = slideReference.length - 1; i >= 0; i--) {
364
429
  const item = slideReference[i];
365
- if (i === slideReference.length - 1 && scrollPosition >= item.trigger) {
430
+ if (i === slideReference.length - 1 && Math.floor(scrollPosition) >= Math.floor(item.trigger)) {
366
431
  snapTarget = item.start;
367
432
  break;
368
433
  }
369
- if (slider.container.scrollLeft >= item.trigger) {
434
+ if (Math.floor(getScrollLeft()) >= Math.floor(item.trigger)) {
370
435
  snapTarget = item.start;
371
436
  break;
372
437
  }
@@ -374,12 +439,12 @@ function Slider(container, options, plugins) {
374
439
  }
375
440
  if (snapTarget !== null) {
376
441
  const offsettedSnapTarget = snapTarget - getLeftOffset();
377
- if (offsettedSnapTarget >= 0) {
442
+ if (Math.floor(offsettedSnapTarget) >= 0) {
378
443
  snapTarget = offsettedSnapTarget;
379
444
  }
380
445
  const scrollBehavior = slider.options.scrollBehavior || 'smooth';
381
446
  slider.container.scrollTo({
382
- left: snapTarget,
447
+ left: slider.options.rtl ? -snapTarget : snapTarget,
383
448
  behavior: scrollBehavior
384
449
  });
385
450
  }
@@ -407,6 +472,10 @@ function Slider(container, options, plugins) {
407
472
  moveToDirection,
408
473
  moveToSlide,
409
474
  snapToClosestSlide,
475
+ getInclusiveScrollWidth,
476
+ getInclusiveClientWidth,
477
+ getScrollLeft,
478
+ setScrollLeft,
410
479
  on,
411
480
  options,
412
481
  };
@@ -1 +1 @@
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
+ import t from"./details.min.js";import{generateId as e,objectsAreEqual as o,getOutermostChildrenEdgeMarginSum as n}from"./utils.min.js";function l(l,i,r){let a,s={};function c(e=!1){const n=a.details,l=t(a);a.details=l,e||o(n,l)?e&&a.emit("detailsChanged"):a.emit("detailsChanged")}function f(){a.slides=Array.from(a.container.querySelectorAll(a.options.slidesSelector))}function d(){a.container.style.setProperty("--slider-container-width",`${a.details.containerWidth}px`),a.container.style.setProperty("--slider-scrollable-width",`${a.details.scrollableAreaWidth}px`),a.container.style.setProperty("--slider-slides-count",`${a.details.slideCount}`)}function h(){a.container.setAttribute("data-has-overflow",a.details.hasOverflow?"true":"false"),a.options.rtl&&a.container.setAttribute("dir","rtl")}function u(t,e=null){const o=e||a.options.scrollBehavior,n=t.getBoundingClientRect(),l=a.container.getBoundingClientRect(),i=a.container.offsetWidth,r=a.container.scrollLeft,s=n.left-l.left+r,c=s+n.width;let f=null;f=Math.floor(s)<Math.floor(r)?s:Math.floor(c)>Math.floor(r)+Math.floor(i)?c-i:0===Math.floor(s)?0:s,null!==f&&setTimeout((t=>{a.emit("programmaticScrollStart"),a.container.scrollTo({left:t,behavior:o})}),50,f)}function g(){const t=a.container.getBoundingClientRect(),e=a.getScrollLeft(),o=a.slides;let n=0,l=!1;if(a.options.rtl){const l=a.getInclusiveScrollWidth()-e-a.getInclusiveClientWidth(),i=[];for(let e=o.length-1;e>=0;e--){const n=o[e].getBoundingClientRect(),r=Math.abs(n.left)-Math.abs(t.left)+l;i.push({slide:o[e],slideEnd:r})}let r=null,s=null;for(let t=0;t<i.length;t++){const e=Math.abs(i[t].slideEnd-l);(null===s||e<s)&&(s=e,r=i[t].slide)}n=r?o.indexOf(r):o.length-1}else for(let i=0;i<o.length;i++){const r=o[i].getBoundingClientRect().left-t.left+e+M();if(Math.floor(r)>=Math.floor(e)){n=i;break}i===o.length-1&&(l=!0)}l&&(n=o.length-1);const i=a.activeSlideIdx;a.activeSlideIdx=n,i!==n&&a.emit("activeSlideChanged")}function m(){return a.options.rtl?Math.abs(a.container.scrollLeft):a.container.scrollLeft}function M(){let t=0;if(a.slides.length>1){const e=a.slides[0].getBoundingClientRect(),o=a.slides[1].getBoundingClientRect();t=a.options.rtl?Math.abs(Math.floor(o.right-e.left)):Math.floor(o.left-e.right)}return t}function p(){let t=0;const e=a.container.getAttribute("data-full-width-offset");return e&&(t=parseInt(e)),Math.floor(t)}return a={emit:function(t){var e;s&&s[t]&&s[t].forEach((t=>{t(a)}));const o=null===(e=null==a?void 0:a.options)||void 0===e?void 0:e[t];"function"==typeof o&&o(a)},moveToDirection:function(t="prev"){const e=a.options.scrollStrategy,o=a.container.scrollLeft,n=a.container.getBoundingClientRect(),l=a.container.offsetWidth;let i=o;const r=a.options.rtl?"prev"===t?"next":"prev":t;if("prev"===r?i=Math.max(0,o-a.container.offsetWidth):"next"===r&&(i=Math.min(a.getInclusiveScrollWidth(),o+a.container.offsetWidth)),"fullSlide"===e){let t=null;if(t="prev"===r?Math.max(0,i-M()):Math.min(a.getInclusiveScrollWidth(),i+M()),"next"===r){let e=!1;for(let l of a.slides){const r=l.getBoundingClientRect(),a=r.left-n.left+o,s=a+r.width;if(Math.floor(a)<Math.floor(i)&&Math.floor(s)>Math.floor(i)){t=a,e=!0;break}}if(e||(t=Math.min(i,a.getInclusiveScrollWidth()-a.container.offsetWidth)),t)if(Math.floor(t)>Math.floor(o)){const e=Math.floor(a.getInclusiveScrollWidth())-Math.floor(l);i=Math.min(t,e)}else i=Math.min(a.getInclusiveScrollWidth(),o+l)}else{let e=!1;for(let i of a.slides){const r=i.getBoundingClientRect(),a=r.left-n.left+o,s=a+r.width;if(Math.floor(a)<Math.floor(o)&&Math.floor(s)>Math.floor(o)){t=s-l,e=!0;break}}e||(t=Math.max(0,o-l)),t&&Math.floor(t)<Math.floor(o)&&(i=t)}}const s=i-p();Math.floor(s)>=0&&(i=s),a.emit("programmaticScrollStart"),a.container.style.scrollBehavior=a.options.scrollBehavior,a.container.scrollLeft=i,setTimeout((()=>a.container.style.scrollBehavior=""),50)},moveToSlide:function(t){const e=a.slides[t];e&&u(e)},snapToClosestSlide:function(t="prev"){const e=a.options.rtl?"prev"===t:"next"===t,o=[];for(let t=0;t<a.slides.length;t++){const e=a.slides[t],n=e.offsetWidth,l=a.options.rtl?Math.abs(e.offsetLeft+n-a.details.containerWidth):e.offsetLeft,i=l+n,r=l+n/2,s=Math.min(r,l+a.options.emulateScrollSnapMaxThreshold);o.push({start:l,middle:r,end:i,width:n,trigger:s,slide:e,offSetleft:e.offsetLeft,rect:e.getBoundingClientRect()})}console.log("slideReference",o);let n=null;const l=m();if(e)for(let t=0;t<o.length;t++){const e=o[t];if(0===t&&Math.floor(l)<=Math.floor(e.trigger)){n=0;break}if(Math.floor(m())<=Math.floor(e.trigger)){n=e.start;break}}else for(let t=o.length-1;t>=0;t--){const e=o[t];if(t===o.length-1&&Math.floor(l)>=Math.floor(e.trigger)){n=e.start;break}if(Math.floor(m())>=Math.floor(e.trigger)){n=e.start;break}}if(null!==n){const t=n-p();Math.floor(t)>=0&&(n=t);const e=a.options.scrollBehavior||"smooth";a.container.scrollTo({left:a.options.rtl?-n:n,behavior:e})}},getInclusiveScrollWidth:function(){return a.container.scrollWidth+n(a.container)},getInclusiveClientWidth:function(){return a.container.clientWidth+n(a.container)},getScrollLeft:m,setScrollLeft:function(t){a.container.scrollLeft=a.options.rtl?-t:t},on:function(t,e){s[t]||(s[t]=[]),s[t].push(e)},options:i},function(){a.container=l;let t=l.getAttribute("id");null===t&&(t=e("overflow-slider"),l.setAttribute("id",t)),f(),c(!0),g(),a.on("contentsChanged",(()=>{f(),c(),g()})),a.on("containerSizeChanged",(()=>c()));let o=0;if(a.on("scroll",(()=>{o&&window.cancelAnimationFrame(o),o=window.requestAnimationFrame((()=>{c(),g()}))})),function(){new MutationObserver((()=>a.emit("contentsChanged"))).observe(a.container,{childList:!0});let t,e,o;new ResizeObserver((()=>a.emit("containerSizeChanged"))).observe(a.container);let n=a.container.scrollLeft,l=a.container.scrollLeft,i=a.container.scrollLeft,r=!1,s=!1,c=!1;a.container.addEventListener("scroll",(()=>{const e=a.container.scrollLeft;Math.floor(n)!==Math.floor(e)&&(r||(r=!0,a.emit("scrollStart")),n=e,clearTimeout(t),t=setTimeout((()=>{r=!1,a.emit("scrollEnd")}),50),a.emit("scroll")),s&&f()}));const f=()=>{const t=a.container.scrollLeft;Math.floor(l)===Math.floor(t)||c||(s||(a.emit("nativeScrollStart"),s=!0),a.emit("nativeScroll"),l=t,clearTimeout(e),e=setTimeout((()=>{s=!1,a.emit("nativeScrollEnd"),i=l}),50))};a.container.addEventListener("touchmove",f),a.container.addEventListener("mousewheel",f),a.container.addEventListener("wheel",f),a.on("programmaticScrollStart",(()=>{c=!0})),a.container.addEventListener("scroll",(()=>{const t=a.container.scrollLeft;Math.floor(i)!==Math.floor(t)&&!s&&c&&(i=t,clearTimeout(o),o=setTimeout((()=>{c=!1,a.emit("programmaticScrollEnd"),l=i}),50),a.emit("programmaticScroll"))})),a.on("programmaticScrollStart",(()=>{a.container.style.scrollSnapType="none"})),a.on("nativeScrollStart",(()=>{a.container.style.scrollSnapType=""}));let d=!1;a.container.addEventListener("mousedown",(()=>{d=!0})),a.container.addEventListener("touchstart",(()=>{d=!0}),{passive:!0}),a.container.addEventListener("focusin",(t=>{if(!d){let e=t.target;for(;e.parentElement!==a.container&&e.parentElement;)e=e.parentElement;u(e,"auto")}d=!1}))}(),h(),d(),r)for(const t of r)t(a);a.on("detailsChanged",(()=>{h(),d()})),a.emit("created"),a.container.setAttribute("data-ready","true")}(),a}export{l as default};
@@ -18,5 +18,19 @@ function objectsAreEqual(obj1, obj2) {
18
18
  }
19
19
  return true;
20
20
  }
21
+ function getOutermostChildrenEdgeMarginSum(el) {
22
+ if (el.children.length === 0) {
23
+ return 0;
24
+ }
25
+ // get the first child and its left margin
26
+ const firstChild = el.children[0];
27
+ const firstChildStyle = getComputedStyle(firstChild);
28
+ const firstChildMarginLeft = parseFloat(firstChildStyle.marginLeft);
29
+ // Get the last child and its right margin
30
+ const lastChild = el.children[el.children.length - 1];
31
+ const lastChildStyle = getComputedStyle(lastChild);
32
+ const lastChildMarginRight = parseFloat(lastChildStyle.marginRight);
33
+ return firstChildMarginLeft + lastChildMarginRight;
34
+ }
21
35
 
22
- export { generateId, objectsAreEqual };
36
+ export { generateId, getOutermostChildrenEdgeMarginSum, objectsAreEqual };
@@ -1 +1 @@
1
- function t(e,n=1){const r=`${e}-${n}`;return document.getElementById(r)?t(e,n+1):r}function e(t,e){const n=Object.keys(t),r=Object.keys(e);if(n.length!==r.length)return!1;for(let r of n)if(!1===e.hasOwnProperty(r)||t[r]!==e[r])return!1;return!0}export{t as generateId,e as objectsAreEqual};
1
+ function e(t,n=1){const r=`${t}-${n}`;return document.getElementById(r)?e(t,n+1):r}function t(e,t){const n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(!1===t.hasOwnProperty(r)||e[r]!==t[r])return!1;return!0}function n(e){if(0===e.children.length)return 0;const t=e.children[0],n=getComputedStyle(t),r=parseFloat(n.marginLeft),o=e.children[e.children.length-1],l=getComputedStyle(o);return r+parseFloat(l.marginRight)}export{e as generateId,n as getOutermostChildrenEdgeMarginSum,t as objectsAreEqual};
@@ -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;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%}
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}[dir=rtl] .overflow-slider-fade--start{left:auto}.overflow-slider-fade--end,[dir=rtl] .overflow-slider-fade--start{background:linear-gradient(to left,var(--overflow-slider-fade-color) 0,transparent 100%);right:0}[dir=rtl] .overflow-slider-fade--end{background:linear-gradient(to right,var(--overflow-slider-fade-color) 0,transparent 100%);left:0;right:auto}[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%}