@evermade/overflow-slider 1.0.0 → 2.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 (78) hide show
  1. package/README.md +74 -8
  2. package/dist/core/details.esm.js +35 -0
  3. package/dist/core/details.min.js +1 -0
  4. package/dist/core/overflow-slider.esm.js +26 -0
  5. package/dist/core/overflow-slider.min.js +1 -0
  6. package/dist/core/slider.esm.js +260 -0
  7. package/dist/core/slider.min.js +1 -0
  8. package/dist/core/utils.esm.js +22 -0
  9. package/dist/core/utils.min.js +1 -0
  10. package/dist/index.esm.js +1 -694
  11. package/dist/index.min.js +1 -2
  12. package/dist/overflow-slider.css +1 -1
  13. package/dist/plugins/arrows/arrows/index.esm.js +82 -0
  14. package/dist/plugins/arrows/arrows/index.min.js +1 -0
  15. package/dist/plugins/dots/dots/index.esm.js +99 -0
  16. package/dist/plugins/dots/dots/index.min.js +1 -0
  17. package/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +70 -0
  18. package/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -0
  19. package/dist/plugins/full-width/full-width/index.esm.js +31 -0
  20. package/dist/plugins/full-width/full-width/index.min.js +1 -0
  21. package/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +133 -0
  22. package/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -0
  23. package/dist/plugins/skip-links/skip-links/index.esm.js +42 -0
  24. package/dist/plugins/skip-links/skip-links/index.min.js +1 -0
  25. package/dist/plugins/thumbnails/thumbnails/index.esm.js +41 -0
  26. package/dist/plugins/thumbnails/thumbnails/index.min.js +1 -0
  27. package/docs/assets/demo.css +151 -5
  28. package/docs/assets/demo.js +107 -10
  29. package/docs/dist/core/details.esm.js +35 -0
  30. package/docs/dist/core/details.min.js +1 -0
  31. package/docs/dist/core/overflow-slider.esm.js +26 -0
  32. package/docs/dist/core/overflow-slider.min.js +1 -0
  33. package/docs/dist/core/slider.esm.js +260 -0
  34. package/docs/dist/core/slider.min.js +1 -0
  35. package/docs/dist/core/utils.esm.js +22 -0
  36. package/docs/dist/core/utils.min.js +1 -0
  37. package/docs/dist/index.esm.js +1 -0
  38. package/docs/dist/index.min.js +1 -0
  39. package/docs/dist/overflow-slider.css +1 -1
  40. package/docs/dist/plugins/arrows/arrows/index.esm.js +82 -0
  41. package/docs/dist/plugins/arrows/arrows/index.min.js +1 -0
  42. package/docs/dist/plugins/dots/dots/index.esm.js +99 -0
  43. package/docs/dist/plugins/dots/dots/index.min.js +1 -0
  44. package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +70 -0
  45. package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -0
  46. package/docs/dist/plugins/full-width/full-width/index.esm.js +31 -0
  47. package/docs/dist/plugins/full-width/full-width/index.min.js +1 -0
  48. package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +133 -0
  49. package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -0
  50. package/docs/dist/plugins/skip-links/skip-links/index.esm.js +42 -0
  51. package/docs/dist/plugins/skip-links/skip-links/index.min.js +1 -0
  52. package/docs/dist/plugins/thumbnails/thumbnails/index.esm.js +41 -0
  53. package/docs/dist/plugins/thumbnails/thumbnails/index.min.js +1 -0
  54. package/docs/index.html +136 -2
  55. package/package.json +35 -6
  56. package/rollup.config.js +58 -32
  57. package/src/core/details.ts +1 -1
  58. package/src/{overflow-slider.ts → core/overflow-slider.ts} +3 -2
  59. package/src/core/slider.ts +62 -16
  60. package/src/core/types.ts +9 -1
  61. package/src/index.ts +1 -12
  62. package/src/overflow-slider.scss +10 -183
  63. package/src/plugins/{arrows.ts → arrows/index.ts} +13 -4
  64. package/src/plugins/arrows/styles.scss +29 -0
  65. package/src/plugins/{dots.ts → dots/index.ts} +1 -1
  66. package/src/plugins/dots/styles.scss +56 -0
  67. package/src/plugins/{drag-scrolling.ts → drag-scrolling/index.ts} +39 -35
  68. package/src/plugins/drag-scrolling/styles.scss +12 -0
  69. package/src/plugins/full-width/index.ts +43 -0
  70. package/src/plugins/{scroll-indicator.ts → scroll-indicator/index.ts} +36 -20
  71. package/src/plugins/scroll-indicator/styles.scss +59 -0
  72. package/src/plugins/{skip-links.ts → skip-links/index.ts} +2 -2
  73. package/src/plugins/skip-links/styles.scss +35 -0
  74. package/src/plugins/thumbnails/index.ts +53 -0
  75. package/tsconfig.json +14 -2
  76. package/dist/index.esm.min.js +0 -2
  77. package/dist/index.js +0 -709
  78. package/docs/dist/overflow-slider.esm.js +0 -694
@@ -94,7 +94,7 @@ textarea {
94
94
  }
95
95
 
96
96
  body {
97
- background-color: #f7f7f7;
97
+ background-color: #fff;
98
98
  }
99
99
 
100
100
  a {
@@ -104,8 +104,7 @@ a {
104
104
  }
105
105
 
106
106
  a:hover,
107
- a:focus-visible,
108
- a:active {
107
+ a:focus-visible {
109
108
  color: var(--color-primary);
110
109
  }
111
110
 
@@ -366,9 +365,9 @@ h3:before {
366
365
  Content
367
366
  =========================================================================== */
368
367
 
369
- .example-container {
370
- gap: var(--slide-gap);
368
+ .overflow-slider {
371
369
  margin-top: 1.5rem;
370
+ gap: 1rem;
372
371
  }
373
372
 
374
373
  .example-item {
@@ -486,6 +485,24 @@ h3:before {
486
485
  scroll-snap-type: x proximity;
487
486
  }
488
487
 
488
+ .example-container-3-entrance-animation a {
489
+ animation: slideEntrance, slideEntrance;
490
+ animation-direction: normal, reverse;
491
+ animation-timeline: view(inline);
492
+ animation-range: entry, exit;
493
+ }
494
+
495
+ @keyframes slideEntrance {
496
+ 0% {
497
+ transform: scale(.75);
498
+ opacity: 0;
499
+ }
500
+ 100% {
501
+ transform: scale(1);
502
+ opacity: 1;
503
+ }
504
+ }
505
+
489
506
  .overflow-slider__dots {
490
507
  margin-top: 1.5rem;
491
508
  }
@@ -511,3 +528,132 @@ h3:before {
511
528
  width: 1.625rem !important;
512
529
  height: 1.625rem !important;
513
530
  }
531
+
532
+ /* ===========================================================================
533
+ Example 4: Filters
534
+ =========================================================================== */
535
+
536
+ .example-4-filters-wrapper {
537
+ display: flex;
538
+ align-items: center;
539
+ gap: .5rem;
540
+ margin-top: 1.5rem;
541
+ position: relative;
542
+ }
543
+
544
+ .example-container-4-filters {
545
+ gap: .75rem;
546
+ margin: 0;
547
+ }
548
+
549
+ .example-4-filters-previous,
550
+ .example-4-filters-next {
551
+ transition: .1s ease-in-out;
552
+ position: absolute;
553
+ top: 0;
554
+ bottom: 0;
555
+ width: var(--example-4-arrow-size);
556
+ display: flex;
557
+ align-items: center;
558
+ background: #fff;
559
+ padding-inline: .5rem;
560
+ }
561
+
562
+ .example-4-filters-previous {
563
+ left: 0;
564
+ }
565
+
566
+ .example-4-filters-next {
567
+ right: 0;
568
+ }
569
+
570
+ .example-4-filters-previous:has([data-has-content="false"]),
571
+ .example-4-filters-next:has([data-has-content="false"]) {
572
+ opacity: 0;
573
+ pointer-events: none;
574
+ visibility: hidden;
575
+ }
576
+
577
+ .example-filter {
578
+ padding: .5rem 1rem;
579
+ border-radius: 2rem;
580
+ background: var(--color-grey-100);
581
+ cursor: pointer;
582
+ color: var(--color-grey-800);
583
+ white-space: nowrap;
584
+ text-decoration: none;
585
+ }
586
+
587
+ .example-filter:hover,
588
+ .example-filter:focus-visible {
589
+ background: var(--color-grey-800);
590
+ color: var(--color-white);
591
+ }
592
+
593
+ /* ===========================================================================
594
+ Example 4: Grid On Desktop
595
+ =========================================================================== */
596
+
597
+ @media (min-width: 768px) {
598
+ .example-container-4-grid-or-slider {
599
+ width: 100%;
600
+ max-width: 100%;
601
+ grid-template-columns: repeat(4, minmax(0, 1fr));
602
+ grid-auto-flow: row;
603
+ overflow: clip;
604
+ }
605
+
606
+ .example-container-4-grid-or-slider .example-item {
607
+ width: 100%;
608
+ }
609
+ }
610
+
611
+ /* ===========================================================================
612
+ Example 4: Full Width
613
+ =========================================================================== */
614
+
615
+ .example-container-4-full-width {
616
+ width: 100vw;
617
+ margin-left: calc(-50vw + 50%);
618
+ }
619
+
620
+ /* ===========================================================================
621
+ Example 4: Synced Sliders
622
+ =========================================================================== */
623
+
624
+ .example-container-4-thumbnails-wrapper {
625
+
626
+ }
627
+
628
+ .example-container-4-synced-main {
629
+ grid-template-columns: repeat(var(--slider-slides-count, 1), var(--slider-container-width, 900px));
630
+ scroll-snap-type: x mandatory;
631
+ }
632
+
633
+ .example-container-4-synced-main .example-item {
634
+ aspect-ratio: 16/8;
635
+ width: 100%;
636
+ max-width: 100%;
637
+ }
638
+
639
+ .example-container-4-synced-thumbnails {
640
+ scroll-snap-type: x proximity;
641
+ }
642
+
643
+ .example-container-4-synced-thumbnails .example-item {
644
+ aspect-ratio: 1/1;
645
+ font-size: 1.5rem;
646
+ width: 120px;
647
+ opacity: .5;
648
+ cursor: pointer;
649
+ }
650
+
651
+ .example-container-4-synced-thumbnails .example-item:hover {
652
+ opacity: .875;
653
+ }
654
+
655
+ .example-container-4-synced-thumbnails .example-item[aria-current="true"] {
656
+ opacity: 1 !important;
657
+ background: var(--color-grey-800);
658
+ color: #fff;
659
+ }
@@ -1,11 +1,23 @@
1
- import {
2
- OverflowSlider,
3
- DragScrollingPlugin,
4
- SkipLinksPlugin,
5
- ArrowsPlugin,
6
- ScrollIndicatorPlugin,
7
- DotsPlugin
8
- } from '../dist/overflow-slider.esm.js';
1
+ /**
2
+ * Hello!
3
+ *
4
+ * This is not how you import files in real project. This is only done this way
5
+ * to make it work with the demo page that cannot import the package from npm.
6
+ *
7
+ * In a real project, you would do something like this:
8
+ *
9
+ * import { OverflowSlider } from '@overflow-slider/core';
10
+ * import DragScrollingPlugin from '@overflow-slider/plugins/drag-scrolling';
11
+ * import SkipLinksPlugin from '@overflow-slider/plugins/skip-links';
12
+ */
13
+ import { OverflowSlider } from '../dist/index.esm.js';
14
+ import DragScrollingPlugin from '../dist/plugins/drag-scrolling/drag-scrolling/index.esm.js';
15
+ import SkipLinksPlugin from '../dist/plugins/skip-links/skip-links/index.esm.js';
16
+ import ArrowsPlugin from '../dist/plugins/arrows/arrows/index.esm.js';
17
+ import ScrollIndicatorPlugin from '../dist/plugins/scroll-indicator/scroll-indicator/index.esm.js';
18
+ import DotsPlugin from '../dist/plugins/dots/dots/index.esm.js';
19
+ import FullWidthPlugin from '../dist/plugins/full-width/full-width/index.esm.js';
20
+ import ThumbnailsPlugin from '../dist/plugins/thumbnails/thumbnails/index.esm.js';
9
21
 
10
22
  (function () {
11
23
  const init = () => {
@@ -16,14 +28,24 @@ import {
16
28
  console.log( '1-css', example1CSS );
17
29
 
18
30
  const example1DragScrolling = new OverflowSlider(
19
- document.querySelector( '.example-container-1-drag-scrolling' ),
31
+ document.querySelector( '.example-container-1-drag-scrolling-clickable' ),
20
32
  {},
21
33
  [
22
34
  DragScrollingPlugin(),
23
35
  SkipLinksPlugin(),
24
36
  ]
25
37
  );
26
- console.log( '1-drag-scrolling', example1DragScrolling );
38
+ console.log( '1-drag-scrolling-clickable', example1DragScrolling );
39
+
40
+ const example1DragScrollingNotClickable = new OverflowSlider(
41
+ document.querySelector( '.example-container-1-drag-scrolling-not-clickable' ),
42
+ {},
43
+ [
44
+ DragScrollingPlugin(),
45
+ SkipLinksPlugin(),
46
+ ]
47
+ );
48
+ console.log( '1-drag-scrolling-not-clickable', example1DragScrollingNotClickable );
27
49
 
28
50
  const example1Arrows = new OverflowSlider(
29
51
  document.querySelector( '.example-container-1-arrows' ),
@@ -107,6 +129,81 @@ import {
107
129
  ]
108
130
  );
109
131
  console.log( '3-scroll-snapping-proximity', example3ScrollSnappingProximity );
132
+
133
+ const example3EntranceAnimation = new OverflowSlider(
134
+ document.querySelector( '.example-container-3-entrance-animation' ),
135
+ {},
136
+ [
137
+ DragScrollingPlugin(),
138
+ ScrollIndicatorPlugin(),
139
+ ]
140
+ );
141
+ console.log( '3-entrance-animation', example3EntranceAnimation );
142
+
143
+ const example4Filters = new OverflowSlider(
144
+ document.querySelector( '.example-container-4-filters' ),
145
+ {},
146
+ [
147
+ DragScrollingPlugin(),
148
+ ArrowsPlugin({
149
+ containerPrev: document.querySelector( '.example-4-filters-previous' ),
150
+ containerNext: document.querySelector( '.example-4-filters-next' ),
151
+ })
152
+ ]
153
+ );
154
+ console.log( '4-filters', example4Filters );
155
+
156
+ const example4GridOrSliders = new OverflowSlider(
157
+ document.querySelector( '.example-container-4-grid-or-slider' ),
158
+ {},
159
+ [
160
+ DragScrollingPlugin(),
161
+ ScrollIndicatorPlugin(),
162
+ ]
163
+ );
164
+ console.log( '4-grid-or-slider', example4GridOrSliders );
165
+
166
+ const example4FullWidth = new OverflowSlider(
167
+ document.querySelector( '.example-container-4-full-width' ),
168
+ {},
169
+ [
170
+ DragScrollingPlugin(),
171
+ FullWidthPlugin(
172
+ {
173
+ targetWidth: (slider) => {
174
+ // copy the width of the parent element
175
+ return slider.container.parentElement.clientWidth;
176
+ }
177
+ }
178
+ ),
179
+ ScrollIndicatorPlugin(),
180
+ ]
181
+ );
182
+ console.log( '4-full-width', example4FullWidth );
183
+
184
+ const example4SyncedMain = new OverflowSlider(
185
+ document.querySelector( '.example-container-4-synced-main' ),
186
+ {},
187
+ [
188
+ DragScrollingPlugin(),
189
+ ]
190
+ );
191
+ console.log( '4-synced-main', example4SyncedMain );
192
+
193
+ const example4SyncedThumbnails = new OverflowSlider(
194
+ document.querySelector( '.example-container-4-synced-thumbnails' ),
195
+ {},
196
+ [
197
+ DragScrollingPlugin(),
198
+ ThumbnailsPlugin({
199
+ mainSlider: example4SyncedMain,
200
+ }),
201
+ ]
202
+ );
203
+ console.log( '4-synced-thumbnails', example4SyncedThumbnails );
204
+
205
+
206
+
110
207
  };
111
208
 
112
209
  init();
@@ -0,0 +1,35 @@
1
+ function details(slider) {
2
+ var _a;
3
+ let instance;
4
+ let hasOverflow = false;
5
+ let slideCount = 0;
6
+ let containerWidth = 0;
7
+ let scrollableAreaWidth = 0;
8
+ let amountOfPages = 0;
9
+ let currentPage = 1;
10
+ if (slider.container.scrollWidth > slider.container.clientWidth) {
11
+ hasOverflow = true;
12
+ }
13
+ slideCount = (_a = slider.slides.length) !== null && _a !== void 0 ? _a : 0;
14
+ containerWidth = slider.container.offsetWidth;
15
+ scrollableAreaWidth = slider.container.scrollWidth;
16
+ amountOfPages = Math.ceil(scrollableAreaWidth / containerWidth);
17
+ if (slider.container.scrollLeft >= 0) {
18
+ currentPage = Math.floor(slider.container.scrollLeft / containerWidth);
19
+ // consider as last page if the scrollLeft + containerWidth is equal to scrollWidth
20
+ if (slider.container.scrollLeft + containerWidth === scrollableAreaWidth) {
21
+ currentPage = amountOfPages - 1;
22
+ }
23
+ }
24
+ instance = {
25
+ hasOverflow,
26
+ slideCount,
27
+ containerWidth,
28
+ scrollableAreaWidth,
29
+ amountOfPages,
30
+ currentPage,
31
+ };
32
+ return instance;
33
+ }
34
+
35
+ export { details as default };
@@ -0,0 +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};
@@ -0,0 +1,26 @@
1
+ import Slider from './slider.esm.js';
2
+
3
+ function OverflowSlider(container, options, plugins) {
4
+ try {
5
+ // check that container HTML element
6
+ if (!(container instanceof Element)) {
7
+ throw new Error(`Container must be HTML element, found ${typeof container}`);
8
+ }
9
+ const defaults = {
10
+ scrollBehavior: "smooth",
11
+ scrollStrategy: "fullSlide",
12
+ slidesSelector: ":scope > *",
13
+ };
14
+ const sliderOptions = Object.assign(Object.assign({}, defaults), options);
15
+ // disable smooth scrolling if user prefers reduced motion
16
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
17
+ sliderOptions.scrollBehavior = "auto";
18
+ }
19
+ return Slider(container, sliderOptions, plugins);
20
+ }
21
+ catch (e) {
22
+ console.error(e);
23
+ }
24
+ }
25
+
26
+ export { OverflowSlider as default };
@@ -0,0 +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};
@@ -0,0 +1,260 @@
1
+ import details from './details.esm.js';
2
+ import { generateId, objectsAreEqual } from './utils.esm.js';
3
+
4
+ function Slider(container, options, plugins) {
5
+ let slider;
6
+ let subs = {};
7
+ function init() {
8
+ slider.container = container;
9
+ // ensure container has id
10
+ let containerId = container.getAttribute('id');
11
+ if (containerId === null) {
12
+ containerId = generateId('overflow-slider');
13
+ container.setAttribute('id', containerId);
14
+ }
15
+ setSlides();
16
+ setDetails(true);
17
+ setActiveSlideIdx();
18
+ slider.on('contentsChanged', () => {
19
+ setSlides();
20
+ setDetails();
21
+ setActiveSlideIdx();
22
+ });
23
+ slider.on('containerSizeChanged', () => setDetails());
24
+ let requestId = 0;
25
+ const setDetailsDebounce = () => {
26
+ if (requestId) {
27
+ window.cancelAnimationFrame(requestId);
28
+ }
29
+ requestId = window.requestAnimationFrame(() => {
30
+ setDetails();
31
+ setActiveSlideIdx();
32
+ });
33
+ };
34
+ slider.on('scroll', setDetailsDebounce);
35
+ addEventListeners();
36
+ setDataAttributes();
37
+ setCSSVariables();
38
+ if (plugins) {
39
+ for (const plugin of plugins) {
40
+ plugin(slider);
41
+ }
42
+ }
43
+ slider.on('detailsChanged', () => {
44
+ setDataAttributes();
45
+ setCSSVariables();
46
+ });
47
+ slider.emit('created');
48
+ slider.container.setAttribute('data-ready', 'true');
49
+ }
50
+ function setDetails(isInit = false) {
51
+ const oldDetails = slider.details;
52
+ const newDetails = details(slider);
53
+ slider.details = newDetails;
54
+ if (!isInit && !objectsAreEqual(oldDetails, newDetails)) {
55
+ slider.emit('detailsChanged');
56
+ }
57
+ else if (isInit) {
58
+ slider.emit('detailsChanged');
59
+ }
60
+ }
61
+ function setSlides() {
62
+ slider.slides = Array.from(slider.container.querySelectorAll(slider.options.slidesSelector));
63
+ }
64
+ function addEventListeners() {
65
+ // changes to DOM
66
+ const observer = new MutationObserver(() => slider.emit('contentsChanged'));
67
+ observer.observe(slider.container, { childList: true });
68
+ // container size changes
69
+ const resizeObserver = new ResizeObserver(() => slider.emit('containerSizeChanged'));
70
+ resizeObserver.observe(slider.container);
71
+ // scroll event with debouncing
72
+ slider.container.addEventListener('scroll', () => slider.emit('scroll'));
73
+ // Listen for mouse down and touch start events on the document
74
+ // This handles both mouse clicks and touch interactions
75
+ let wasInteractedWith = false;
76
+ slider.container.addEventListener('mousedown', () => {
77
+ wasInteractedWith = true;
78
+ });
79
+ slider.container.addEventListener('touchstart', () => {
80
+ wasInteractedWith = true;
81
+ }, { passive: true });
82
+ slider.container.addEventListener('focusin', (e) => {
83
+ // move target parents as long as they are not the container
84
+ // but only if focus didn't start from mouse or touch
85
+ if (!wasInteractedWith) {
86
+ let target = e.target;
87
+ while (target.parentElement !== slider.container) {
88
+ if (target.parentElement) {
89
+ target = target.parentElement;
90
+ }
91
+ else {
92
+ break;
93
+ }
94
+ }
95
+ ensureSlideIsInView(target);
96
+ }
97
+ wasInteractedWith = false;
98
+ });
99
+ }
100
+ function setCSSVariables() {
101
+ slider.container.style.setProperty('--slider-container-width', `${slider.details.containerWidth}px`);
102
+ slider.container.style.setProperty('--slider-scrollable-width', `${slider.details.scrollableAreaWidth}px`);
103
+ slider.container.style.setProperty('--slider-slides-count', `${slider.details.slideCount}`);
104
+ }
105
+ function setDataAttributes() {
106
+ slider.container.setAttribute('data-has-overflow', slider.details.hasOverflow ? 'true' : 'false');
107
+ }
108
+ function ensureSlideIsInView(slide) {
109
+ const slideRect = slide.getBoundingClientRect();
110
+ const sliderRect = slider.container.getBoundingClientRect();
111
+ const containerWidth = slider.container.offsetWidth;
112
+ const scrollLeft = slider.container.scrollLeft;
113
+ const slideStart = slideRect.left - sliderRect.left + scrollLeft;
114
+ const slideEnd = slideStart + slideRect.width;
115
+ let scrollTarget = null;
116
+ if (slideStart < scrollLeft) {
117
+ scrollTarget = slideStart;
118
+ }
119
+ else if (slideEnd > scrollLeft + containerWidth) {
120
+ scrollTarget = slideEnd - containerWidth;
121
+ }
122
+ else if (slideStart === 0) {
123
+ scrollTarget = 0;
124
+ }
125
+ if (scrollTarget !== null) {
126
+ slider.container.style.scrollSnapType = 'none';
127
+ slider.container.scrollLeft = scrollTarget;
128
+ // @todo resume scroll snapping but at least proximity gives a lot of trouble
129
+ // and it's not really needed for this use case but it would be nice to have
130
+ // it back in case it's needed. We need to calculate scrollLeft some other way
131
+ }
132
+ }
133
+ function setActiveSlideIdx() {
134
+ const sliderRect = slider.container.getBoundingClientRect();
135
+ const scrollLeft = slider.container.scrollLeft;
136
+ const slides = slider.slides;
137
+ let activeSlideIdx = 0;
138
+ for (let i = 0; i < slides.length; i++) {
139
+ const slideRect = slides[i].getBoundingClientRect();
140
+ const slideStart = slideRect.left - sliderRect.left + scrollLeft + getGapSize();
141
+ if (slideStart > scrollLeft) {
142
+ activeSlideIdx = i;
143
+ break;
144
+ }
145
+ }
146
+ const oldActiveSlideIdx = slider.activeSlideIdx;
147
+ slider.activeSlideIdx = activeSlideIdx;
148
+ if (oldActiveSlideIdx !== activeSlideIdx) {
149
+ slider.emit('activeSlideChanged');
150
+ }
151
+ }
152
+ function moveToSlide(idx) {
153
+ const slide = slider.slides[idx];
154
+ if (slide) {
155
+ ensureSlideIsInView(slide);
156
+ }
157
+ }
158
+ function getGapSize() {
159
+ let gapSize = 0;
160
+ if (slider.slides.length > 1) {
161
+ const firstSlideRect = slider.slides[0].getBoundingClientRect();
162
+ const secondSlideRect = slider.slides[1].getBoundingClientRect();
163
+ gapSize = secondSlideRect.left - firstSlideRect.right;
164
+ }
165
+ return gapSize;
166
+ }
167
+ function moveToDirection(direction = "prev") {
168
+ const scrollStrategy = slider.options.scrollStrategy;
169
+ const scrollLeft = slider.container.scrollLeft;
170
+ const sliderRect = slider.container.getBoundingClientRect();
171
+ const containerWidth = slider.container.offsetWidth;
172
+ let targetScrollPosition = scrollLeft;
173
+ if (direction === 'prev') {
174
+ targetScrollPosition = Math.max(0, scrollLeft - slider.container.offsetWidth);
175
+ }
176
+ else if (direction === 'next') {
177
+ targetScrollPosition = Math.min(slider.container.scrollWidth, scrollLeft + slider.container.offsetWidth);
178
+ }
179
+ if (scrollStrategy === 'fullSlide') {
180
+ let fullSldeTargetScrollPosition = null;
181
+ // extend targetScrollPosition to include gap
182
+ if (direction === 'prev') {
183
+ fullSldeTargetScrollPosition = Math.max(0, targetScrollPosition - getGapSize());
184
+ }
185
+ else {
186
+ fullSldeTargetScrollPosition = Math.min(slider.container.scrollWidth, targetScrollPosition + getGapSize());
187
+ }
188
+ if (direction === 'next') {
189
+ let partialSlideFound = false;
190
+ for (let slide of slider.slides) {
191
+ const slideRect = slide.getBoundingClientRect();
192
+ const slideStart = slideRect.left - sliderRect.left + scrollLeft;
193
+ const slideEnd = slideStart + slideRect.width;
194
+ if (slideStart < targetScrollPosition && slideEnd > targetScrollPosition) {
195
+ fullSldeTargetScrollPosition = slideStart;
196
+ partialSlideFound = true;
197
+ break;
198
+ }
199
+ }
200
+ if (!partialSlideFound) {
201
+ fullSldeTargetScrollPosition = Math.min(targetScrollPosition, slider.container.scrollWidth - slider.container.offsetWidth);
202
+ }
203
+ if (fullSldeTargetScrollPosition && fullSldeTargetScrollPosition > scrollLeft) {
204
+ targetScrollPosition = fullSldeTargetScrollPosition;
205
+ }
206
+ }
207
+ else {
208
+ let partialSlideFound = false;
209
+ for (let slide of slider.slides) {
210
+ const slideRect = slide.getBoundingClientRect();
211
+ const slideStart = slideRect.left - sliderRect.left + scrollLeft;
212
+ const slideEnd = slideStart + slideRect.width;
213
+ if (slideStart < scrollLeft && slideEnd > scrollLeft) {
214
+ fullSldeTargetScrollPosition = slideEnd - containerWidth;
215
+ partialSlideFound = true;
216
+ break;
217
+ }
218
+ }
219
+ if (!partialSlideFound) {
220
+ fullSldeTargetScrollPosition = Math.max(0, scrollLeft - containerWidth);
221
+ }
222
+ if (fullSldeTargetScrollPosition && fullSldeTargetScrollPosition < scrollLeft) {
223
+ targetScrollPosition = fullSldeTargetScrollPosition;
224
+ }
225
+ }
226
+ }
227
+ slider.container.style.scrollBehavior = slider.options.scrollBehavior;
228
+ slider.container.scrollLeft = targetScrollPosition;
229
+ setTimeout(() => slider.container.style.scrollBehavior = '', 50);
230
+ }
231
+ function on(name, cb) {
232
+ if (!subs[name]) {
233
+ subs[name] = [];
234
+ }
235
+ subs[name].push(cb);
236
+ }
237
+ function emit(name) {
238
+ var _a;
239
+ if (subs && subs[name]) {
240
+ subs[name].forEach(cb => {
241
+ cb(slider);
242
+ });
243
+ }
244
+ const optionCallBack = (_a = slider === null || slider === void 0 ? void 0 : slider.options) === null || _a === void 0 ? void 0 : _a[name];
245
+ if (typeof optionCallBack === 'function') {
246
+ optionCallBack(slider);
247
+ }
248
+ }
249
+ slider = {
250
+ emit,
251
+ moveToDirection,
252
+ moveToSlide,
253
+ on,
254
+ options,
255
+ };
256
+ init();
257
+ return slider;
258
+ }
259
+
260
+ export { Slider as default };
@@ -0,0 +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){const t=e.getBoundingClientRect(),n=r.container.getBoundingClientRect(),i=r.container.offsetWidth,o=r.container.scrollLeft,l=t.left-n.left+o,s=l+t.width;let a=null;l<o?a=l:s>o+i?a=s-i:0===l&&(a=0),null!==a&&(r.container.style.scrollSnapType="none",r.container.scrollLeft=a)}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+g()>t){i=o;break}}const o=r.activeSlideIdx;r.activeSlideIdx=i,o!==i&&r.emit("activeSlideChanged")}function g(){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-g()):Math.min(r.container.scrollWidth,l+g()),"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)}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};
@@ -0,0 +1,22 @@
1
+ function generateId(prefix, i = 1) {
2
+ const id = `${prefix}-${i}`;
3
+ if (document.getElementById(id)) {
4
+ return generateId(prefix, i + 1);
5
+ }
6
+ return id;
7
+ }
8
+ function objectsAreEqual(obj1, obj2) {
9
+ const keys1 = Object.keys(obj1);
10
+ const keys2 = Object.keys(obj2);
11
+ if (keys1.length !== keys2.length) {
12
+ return false;
13
+ }
14
+ for (let key of keys1) {
15
+ if (obj2.hasOwnProperty(key) === false || obj1[key] !== obj2[key]) {
16
+ return false;
17
+ }
18
+ }
19
+ return true;
20
+ }
21
+
22
+ export { generateId, objectsAreEqual };
@@ -0,0 +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};