@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.
- package/README.md +73 -8
- package/dist/core/details.esm.js +5 -5
- package/dist/core/details.min.js +1 -1
- package/dist/core/overflow-slider.esm.js +1 -0
- package/dist/core/overflow-slider.min.js +1 -1
- package/dist/core/slider.esm.js +113 -44
- package/dist/core/slider.min.js +1 -1
- package/dist/core/utils.esm.js +15 -1
- package/dist/core/utils.min.js +1 -1
- package/dist/overflow-slider.css +1 -1
- package/dist/plugins/arrows/arrows/index.esm.js +20 -10
- package/dist/plugins/arrows/arrows/index.min.js +1 -1
- package/dist/plugins/dots/dots/index.esm.js +0 -4
- package/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +1 -1
- package/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -1
- package/dist/plugins/fade/fade/index.esm.js +7 -7
- package/dist/plugins/fade/fade/index.min.js +1 -1
- package/dist/plugins/full-width/full-width/index.esm.js +7 -2
- package/dist/plugins/full-width/full-width/index.min.js +1 -1
- package/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +22 -22
- package/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -1
- package/dist/plugins/thumbnails/thumbnails/index.esm.js +7 -4
- package/dist/plugins/thumbnails/thumbnails/index.min.js +1 -1
- package/docs/assets/demo.css +11 -1
- package/docs/assets/demo.js +38 -12
- package/docs/dist/core/details.esm.js +5 -5
- package/docs/dist/core/details.min.js +1 -1
- package/docs/dist/core/overflow-slider.esm.js +1 -0
- package/docs/dist/core/overflow-slider.min.js +1 -1
- package/docs/dist/core/slider.esm.js +113 -44
- package/docs/dist/core/slider.min.js +1 -1
- package/docs/dist/core/utils.esm.js +15 -1
- package/docs/dist/core/utils.min.js +1 -1
- package/docs/dist/overflow-slider.css +1 -1
- package/docs/dist/plugins/arrows/arrows/index.esm.js +20 -10
- package/docs/dist/plugins/arrows/arrows/index.min.js +1 -1
- package/docs/dist/plugins/dots/dots/index.esm.js +0 -4
- package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.esm.js +1 -1
- package/docs/dist/plugins/drag-scrolling/drag-scrolling/index.min.js +1 -1
- package/docs/dist/plugins/fade/fade/index.esm.js +7 -7
- package/docs/dist/plugins/fade/fade/index.min.js +1 -1
- package/docs/dist/plugins/full-width/full-width/index.esm.js +7 -2
- package/docs/dist/plugins/full-width/full-width/index.min.js +1 -1
- package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.esm.js +22 -22
- package/docs/dist/plugins/scroll-indicator/scroll-indicator/index.min.js +1 -1
- package/docs/dist/plugins/thumbnails/thumbnails/index.esm.js +7 -4
- package/docs/dist/plugins/thumbnails/thumbnails/index.min.js +1 -1
- package/docs/index-rtl.html +396 -0
- package/docs/index.html +1 -1
- package/package.json +1 -1
- package/src/core/details.ts +5 -5
- package/src/core/overflow-slider.ts +1 -0
- package/src/core/slider.ts +125 -47
- package/src/core/types.ts +5 -0
- package/src/core/utils.ts +19 -1
- package/src/plugins/arrows/index.ts +20 -10
- package/src/plugins/dots/index.ts +0 -4
- package/src/plugins/drag-scrolling/index.ts +1 -1
- package/src/plugins/fade/index.ts +7 -8
- package/src/plugins/fade/styles.scss +10 -0
- package/src/plugins/full-width/index.ts +8 -2
- package/src/plugins/scroll-indicator/index.ts +62 -64
- package/src/plugins/thumbnails/index.ts +7 -5
|
@@ -15,8 +15,8 @@ export type ScrollIndicatorOptions = {
|
|
|
15
15
|
container: HTMLElement | null,
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export default function ScrollIndicatorPlugin(
|
|
19
|
-
return (
|
|
18
|
+
export default function ScrollIndicatorPlugin(args: { [key: string]: any }) {
|
|
19
|
+
return (slider: Slider) => {
|
|
20
20
|
|
|
21
21
|
const options = <ScrollIndicatorOptions>{
|
|
22
22
|
classNames: {
|
|
@@ -26,109 +26,107 @@ export default function ScrollIndicatorPlugin( args: { [key: string]: any } ) {
|
|
|
26
26
|
container: args?.container ?? null,
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const scrollbarContainer = document.createElement('div');
|
|
30
|
+
scrollbarContainer.setAttribute('class', options.classNames.scrollIndicator);
|
|
31
|
+
scrollbarContainer.setAttribute('tabindex', '0');
|
|
32
|
+
scrollbarContainer.setAttribute('role', 'scrollbar');
|
|
33
|
+
scrollbarContainer.setAttribute('aria-controls', slider.container.getAttribute('id') ?? '');
|
|
34
|
+
scrollbarContainer.setAttribute('aria-orientation', 'horizontal');
|
|
35
|
+
scrollbarContainer.setAttribute('aria-valuemax', '100');
|
|
36
|
+
scrollbarContainer.setAttribute('aria-valuemin', '0');
|
|
37
|
+
scrollbarContainer.setAttribute('aria-valuenow', '0');
|
|
29
38
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
scrollbarContainer.setAttribute( 'tabindex', '0' );
|
|
33
|
-
scrollbarContainer.setAttribute( 'role', 'scrollbar' );
|
|
34
|
-
scrollbarContainer.setAttribute( 'aria-controls', slider.container.getAttribute( 'id' ) ?? '' );
|
|
35
|
-
scrollbarContainer.setAttribute( 'aria-orientation', 'horizontal' );
|
|
36
|
-
scrollbarContainer.setAttribute( 'aria-valuemax', '100' );
|
|
37
|
-
scrollbarContainer.setAttribute( 'aria-valuemin', '0' );
|
|
38
|
-
scrollbarContainer.setAttribute( 'aria-valuenow', '0' );
|
|
39
|
+
const scrollbar = document.createElement('div');
|
|
40
|
+
scrollbar.setAttribute('class', options.classNames.scrollIndicatorBar);
|
|
39
41
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
+
const scrollbarButton = document.createElement('div');
|
|
43
|
+
scrollbarButton.setAttribute('class', options.classNames.scrollIndicatorButton);
|
|
44
|
+
scrollbarButton.setAttribute('data-is-grabbed', 'false');
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
scrollbarButton.setAttribute( 'data-is-grabbed', 'false' );
|
|
46
|
-
|
|
47
|
-
scrollbar.appendChild( scrollbarButton );
|
|
48
|
-
scrollbarContainer.appendChild( scrollbar );
|
|
46
|
+
scrollbar.appendChild(scrollbarButton);
|
|
47
|
+
scrollbarContainer.appendChild(scrollbar);
|
|
49
48
|
|
|
50
49
|
const setDataAttributes = () => {
|
|
51
|
-
scrollbarContainer.setAttribute(
|
|
50
|
+
scrollbarContainer.setAttribute('data-has-overflow', slider.details.hasOverflow.toString());
|
|
52
51
|
}
|
|
53
52
|
setDataAttributes();
|
|
54
53
|
|
|
55
54
|
const getScrollbarButtonLeftOffset = () => {
|
|
56
|
-
const
|
|
57
|
-
|
|
55
|
+
const contentRatio = scrollbarButton.offsetWidth / slider.details.containerWidth;
|
|
56
|
+
const scrollAmount = slider.getScrollLeft() * contentRatio;
|
|
57
|
+
if (slider.options.rtl) {
|
|
58
|
+
return scrollbar.offsetWidth - scrollbarButton.offsetWidth - scrollAmount;
|
|
59
|
+
}
|
|
60
|
+
return scrollAmount;
|
|
58
61
|
};
|
|
59
62
|
|
|
60
|
-
// scrollbarbutton width and position is calculated based on the scroll position and available width
|
|
61
63
|
let requestId = 0;
|
|
62
64
|
const update = () => {
|
|
63
|
-
if (
|
|
64
|
-
window.cancelAnimationFrame(
|
|
65
|
+
if (requestId) {
|
|
66
|
+
window.cancelAnimationFrame(requestId);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
requestId = window.requestAnimationFrame(() => {
|
|
68
|
-
const scrollbarButtonWidth = (slider.details.containerWidth / slider.
|
|
70
|
+
const scrollbarButtonWidth = (slider.details.containerWidth / slider.container.scrollWidth) * 100;
|
|
69
71
|
|
|
70
72
|
const scrollLeftInPortion = getScrollbarButtonLeftOffset();
|
|
71
73
|
scrollbarButton.style.width = `${scrollbarButtonWidth}%`;
|
|
72
74
|
scrollbarButton.style.transform = `translateX(${scrollLeftInPortion}px)`;
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
const scrollWidth = slider.container.scrollWidth;
|
|
76
|
+
const scrollLeft = slider.getScrollLeft();
|
|
77
|
+
const scrollWidth = slider.getInclusiveScrollWidth();
|
|
77
78
|
const containerWidth = slider.container.offsetWidth;
|
|
78
79
|
const scrollPercentage = (scrollLeft / (scrollWidth - containerWidth)) * 100;
|
|
79
|
-
scrollbarContainer.setAttribute(
|
|
80
|
+
scrollbarContainer.setAttribute('aria-valuenow', Math.round(Number.isNaN(scrollPercentage) ? 0 : scrollPercentage).toString());
|
|
80
81
|
});
|
|
81
82
|
};
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
options.container.appendChild( scrollbarContainer );
|
|
84
|
+
if (options.container) {
|
|
85
|
+
options.container.appendChild(scrollbarContainer);
|
|
86
86
|
} else {
|
|
87
|
-
slider.container.parentNode?.insertBefore(
|
|
87
|
+
slider.container.parentNode?.insertBefore(scrollbarContainer, slider.container.nextSibling);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
// update the scrollbar when the slider is scrolled
|
|
91
90
|
update();
|
|
92
|
-
slider.on(
|
|
93
|
-
slider.on(
|
|
94
|
-
slider.on(
|
|
95
|
-
slider.on(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
slider.moveToDirection( 'next' );
|
|
91
|
+
slider.on('scroll', update);
|
|
92
|
+
slider.on('contentsChanged', update);
|
|
93
|
+
slider.on('containerSizeChanged', update);
|
|
94
|
+
slider.on('detailsChanged', setDataAttributes);
|
|
95
|
+
|
|
96
|
+
scrollbarContainer.addEventListener('keydown', (e) => {
|
|
97
|
+
if (e.key === 'ArrowLeft') {
|
|
98
|
+
slider.moveToDirection('prev');
|
|
99
|
+
} else if (e.key === 'ArrowRight') {
|
|
100
|
+
slider.moveToDirection('next');
|
|
103
101
|
}
|
|
104
102
|
});
|
|
105
103
|
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
let isInteractionDown = false;
|
|
105
|
+
let startX = 0;
|
|
106
|
+
let scrollLeft = slider.getScrollLeft();
|
|
107
|
+
|
|
108
|
+
scrollbarContainer.addEventListener('click', (e) => {
|
|
109
|
+
if ( e.target == scrollbarButton ) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
108
112
|
const scrollbarButtonWidth = scrollbarButton.offsetWidth;
|
|
109
113
|
const scrollbarButtonLeft = getScrollbarButtonLeftOffset();
|
|
110
114
|
const scrollbarButtonRight = scrollbarButtonLeft + scrollbarButtonWidth;
|
|
111
|
-
const clickX = e.pageX - scrollbarContainer.offsetLeft;
|
|
112
|
-
if (
|
|
113
|
-
slider.moveToDirection( 'prev'
|
|
114
|
-
} else if (
|
|
115
|
-
slider.moveToDirection( 'next'
|
|
115
|
+
const clickX = e.pageX - Math.abs( scrollbarContainer.offsetLeft );
|
|
116
|
+
if (Math.floor(clickX) < Math.floor(scrollbarButtonLeft)) {
|
|
117
|
+
slider.moveToDirection(slider.options.rtl ? 'next' : 'prev');
|
|
118
|
+
} else if (Math.floor(clickX) > Math.floor(scrollbarButtonRight)) {
|
|
119
|
+
slider.moveToDirection(slider.options.rtl ? 'prev' : 'next');
|
|
116
120
|
}
|
|
117
121
|
});
|
|
118
122
|
|
|
119
|
-
// make scrollbar button draggable via mouse/touch and update the scroll position
|
|
120
|
-
let isInteractionDown = false;
|
|
121
|
-
let startX = 0;
|
|
122
|
-
let scrollLeft = 0;
|
|
123
|
-
|
|
124
123
|
const onInteractionDown = (e: MouseEvent | TouchEvent) => {
|
|
125
124
|
isInteractionDown = true;
|
|
126
125
|
const pageX = (e as MouseEvent).pageX || (e as TouchEvent).touches[0].pageX;
|
|
127
126
|
startX = pageX - scrollbarContainer.offsetLeft;
|
|
128
|
-
scrollLeft = slider.
|
|
129
|
-
// change cursor to grabbing
|
|
127
|
+
scrollLeft = slider.getScrollLeft();
|
|
130
128
|
scrollbarButton.style.cursor = 'grabbing';
|
|
131
|
-
scrollbarButton.setAttribute(
|
|
129
|
+
scrollbarButton.setAttribute('data-is-grabbed', 'true');
|
|
132
130
|
|
|
133
131
|
e.preventDefault();
|
|
134
132
|
e.stopPropagation();
|
|
@@ -144,13 +142,14 @@ export default function ScrollIndicatorPlugin( args: { [key: string]: any } ) {
|
|
|
144
142
|
const scrollingFactor = slider.details.scrollableAreaWidth / scrollbarContainer.offsetWidth;
|
|
145
143
|
|
|
146
144
|
const walk = (x - startX) * scrollingFactor;
|
|
147
|
-
slider.
|
|
145
|
+
const distance = slider.options.rtl ? scrollLeft - walk : scrollLeft + walk;
|
|
146
|
+
slider.setScrollLeft(distance);
|
|
148
147
|
};
|
|
149
148
|
|
|
150
149
|
const onInteractionUp = () => {
|
|
151
150
|
isInteractionDown = false;
|
|
152
151
|
scrollbarButton.style.cursor = '';
|
|
153
|
-
scrollbarButton.setAttribute(
|
|
152
|
+
scrollbarButton.setAttribute('data-is-grabbed', 'false');
|
|
154
153
|
};
|
|
155
154
|
|
|
156
155
|
scrollbarButton.addEventListener('mousedown', onInteractionDown);
|
|
@@ -161,6 +160,5 @@ export default function ScrollIndicatorPlugin( args: { [key: string]: any } ) {
|
|
|
161
160
|
|
|
162
161
|
window.addEventListener('mouseup', onInteractionUp);
|
|
163
162
|
window.addEventListener('touchend', onInteractionUp);
|
|
164
|
-
|
|
165
163
|
};
|
|
166
164
|
}
|
|
@@ -13,7 +13,6 @@ export default function FullWidthPlugin( args: { [key: string]: any } ) {
|
|
|
13
13
|
|
|
14
14
|
const mainSlider = options.mainSlider;
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
const setActiveThumbnail = (slide: HTMLElement | null = null) => {
|
|
18
17
|
if ( slide === null && slider.slides.length > 0 ) {
|
|
19
18
|
slide = slider.slides[0] as HTMLElement;
|
|
@@ -40,13 +39,16 @@ export default function FullWidthPlugin( args: { [key: string]: any } ) {
|
|
|
40
39
|
setActiveThumbnail();
|
|
41
40
|
addClickListeners();
|
|
42
41
|
|
|
43
|
-
// @todo debounce on scroll
|
|
44
42
|
mainSlider.on( 'scrollEnd', () => {
|
|
45
43
|
setTimeout(() => {
|
|
46
|
-
const
|
|
47
|
-
const
|
|
44
|
+
const mainActiveSlideIdx = mainSlider.activeSlideIdx;
|
|
45
|
+
const thumbActiveSlideIdx = slider.activeSlideIdx;
|
|
46
|
+
if ( thumbActiveSlideIdx === mainActiveSlideIdx ) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const activeThumbnail = slider.slides[mainActiveSlideIdx] as HTMLElement;
|
|
48
50
|
setActiveThumbnail(activeThumbnail);
|
|
49
|
-
slider.moveToSlide(
|
|
51
|
+
slider.moveToSlide(mainActiveSlideIdx);
|
|
50
52
|
}, 50);
|
|
51
53
|
});
|
|
52
54
|
|