@yoursurprise/slider 0.0.20 → 0.0.22
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 +9 -5
- package/dist/Components/Controls/NextButton.d.ts +8 -0
- package/dist/Components/Controls/PreviousButton.d.ts +8 -0
- package/dist/Hooks/UseSider.test.d.ts +1 -0
- package/dist/Hooks/UseSlider.d.ts +22 -0
- package/dist/Slider.d.ts +5 -1
- package/dist/index.css +13 -4
- package/dist/index.css.map +1 -1
- package/dist/index.js +168 -68
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
- package/src/Components/Controls/Button.scss +42 -0
- package/src/Components/Controls/NextButton.tsx +28 -0
- package/src/Components/Controls/PreviousButton.tsx +28 -0
- package/src/Hooks/UseSider.test.ts +123 -0
- package/src/Hooks/UseSlider.ts +84 -0
- package/src/Slider.scss +0 -37
- package/src/Slider.test.tsx +55 -29
- package/src/Slider.tsx +67 -107
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ This slider has the following features:
|
|
|
15
15
|
Before using this slider, please consider the following:
|
|
16
16
|
- This project is still being set up, this is an alpha version
|
|
17
17
|
- The slider only contains styling to make it functional
|
|
18
|
-
- There is no configuration of aforementioned features (yet)
|
|
18
|
+
- There is no configuration of most aforementioned features (yet)
|
|
19
19
|
|
|
20
20
|
Todos:
|
|
21
21
|
- ~~Add a demo page~~
|
|
@@ -39,11 +39,13 @@ All browsers with [IntersectionObserver](https://developer.mozilla.org/en-US/doc
|
|
|
39
39
|
|
|
40
40
|
### Import the CSS files
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
```javascript
|
|
43
|
+
import "@yoursurprise/slider/dist/index.css";
|
|
44
|
+
```
|
|
43
45
|
|
|
44
46
|
### Implement the Slider
|
|
45
47
|
|
|
46
|
-
```
|
|
48
|
+
```javascript
|
|
47
49
|
import { Slider } from '@yoursurprise/slider';
|
|
48
50
|
import '@yoursurprise/slider/dist/index.css';
|
|
49
51
|
|
|
@@ -59,6 +61,8 @@ export default function YourComponent() {
|
|
|
59
61
|
}
|
|
60
62
|
```
|
|
61
63
|
|
|
64
|
+
### Configuration
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
| Option | Type | Required | Default | Description |
|
|
67
|
+
|-----------------------|-----------|----------|---------|-------------------------------------|
|
|
68
|
+
| hideNavigationButtons | `boolean` | `false` | `false` | Always hides the navigation buttons |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare enum Visibility {
|
|
2
|
+
FULL = 0,
|
|
3
|
+
PARTIAL = 1,
|
|
4
|
+
NONE = 2
|
|
5
|
+
}
|
|
6
|
+
export declare enum NavigationDirection {
|
|
7
|
+
PREV = 0,
|
|
8
|
+
NEXT = 1
|
|
9
|
+
}
|
|
10
|
+
interface UseSlider {
|
|
11
|
+
getLeftPositionToScrollTo: (direction: NavigationDirection, slideOffsetLeft: number, wrapperOffsetLeft: number, wrapperWidth: number, slideWidth: number) => number;
|
|
12
|
+
getVisibilityByIntersectionRatio: (intersectionRatio: number) => Visibility;
|
|
13
|
+
getFirstVisibleSlideIndex: () => number;
|
|
14
|
+
getLastVisibleSlideIndex: () => number;
|
|
15
|
+
addVisibleSlide: (index: number) => void;
|
|
16
|
+
addPartiallyVisibleSlide: (index: number) => void;
|
|
17
|
+
sortSlides: () => void;
|
|
18
|
+
removeVisibleSlide: (index: number) => void;
|
|
19
|
+
removePartiallyVisibleSlide: (index: number) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare const useSlider: () => UseSlider;
|
|
22
|
+
export {};
|
package/dist/Slider.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { PropsWithChildren } from 'react';
|
|
3
3
|
import './Slider.scss';
|
|
4
|
-
|
|
4
|
+
interface Settings {
|
|
5
|
+
hideNavigationButtons?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const Slider: React.FC<PropsWithChildren<Settings>>;
|
|
8
|
+
export {};
|
package/dist/index.css
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
.slider {
|
|
2
|
-
position: relative;
|
|
3
|
-
}
|
|
4
1
|
.slider__button {
|
|
5
2
|
position: absolute;
|
|
6
3
|
top: 0;
|
|
@@ -9,12 +6,21 @@
|
|
|
9
6
|
width: 48px;
|
|
10
7
|
margin: auto 0;
|
|
11
8
|
border-radius: 50%;
|
|
12
|
-
border: 1px solid #C9C9C9;
|
|
13
9
|
background-color: white;
|
|
14
10
|
align-items: center;
|
|
15
11
|
justify-content: center;
|
|
16
12
|
cursor: pointer;
|
|
17
13
|
display: none;
|
|
14
|
+
border: none;
|
|
15
|
+
outline: none;
|
|
16
|
+
box-shadow: inset 0 0 0 1px rgba(32, 32, 32, 0.1);
|
|
17
|
+
transition: box-shadow 0.2s ease-in-out;
|
|
18
|
+
}
|
|
19
|
+
.slider__button__icon {
|
|
20
|
+
fill: #554c44;
|
|
21
|
+
}
|
|
22
|
+
.slider__button:hover {
|
|
23
|
+
box-shadow: inset 0 0 0 1px rgba(32, 32, 32, 0.2);
|
|
18
24
|
}
|
|
19
25
|
@media (hover: hover) {
|
|
20
26
|
.slider__button {
|
|
@@ -30,6 +36,9 @@
|
|
|
30
36
|
.slider__button--prev {
|
|
31
37
|
left: 5px;
|
|
32
38
|
}
|
|
39
|
+
.slider {
|
|
40
|
+
position: relative;
|
|
41
|
+
}
|
|
33
42
|
.slider__wrapper {
|
|
34
43
|
overscroll-behavior-x: contain;
|
|
35
44
|
-ms-overflow-style: none;
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["Slider.scss"],"names":[],"mappings":"AAAA;EACE,kBAAkB;
|
|
1
|
+
{"version":3,"sources":["Button.scss","Slider.scss"],"names":[],"mappings":"AAAA;EACE,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,YAAY;EACZ,WAAW;EACX,cAAc;EACd,kBAAkB;EAClB,uBAAuB;EACvB,mBAAmB;EACnB,uBAAuB;EACvB,eAAe;EACf,aAAa;EACb,YAAY;EACZ,aAAa;EACb,iDAAiD;EACjD,uCAAuC;AACzC;AACA;EACE,aAAa;AACf;AACA;EACE,iDAAiD;AACnD;AACA;EACE;IACE,aAAa;EACf;AACF;AACA;EACE,aAAa;AACf;AACA;EACE,UAAU;AACZ;AACA;EACE,SAAS;AACX;ACrCA;EACE,kBAAkB;AACpB;AACA;EACE,8BAA8B;EAC9B,wBAAwB;EACxB,qBAAqB;EACrB,aAAa;EACb,mBAAmB;EACnB,gBAAgB;EAChB,6BAA6B;AAC/B;AACA;EACE,aAAa;AACf;AACA;EACE;IACE,yBAAyB;EAC3B;AACF;AACA;EACE,uBAAuB;AACzB;AACA;EACE,YAAY;AACd;AACA;EACE,gBAAgB;EAChB,iBAAiB;AACnB;AACA;EACE,wBAAwB;AAC1B","file":"index.css","sourcesContent":[".slider__button {\n position: absolute;\n top: 0;\n bottom: 0;\n height: 48px;\n width: 48px;\n margin: auto 0;\n border-radius: 50%;\n background-color: white;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n display: none;\n border: none;\n outline: none;\n box-shadow: inset 0 0 0 1px rgba(32, 32, 32, 0.1);\n transition: box-shadow 0.2s ease-in-out;\n}\n.slider__button__icon {\n fill: #554c44;\n}\n.slider__button:hover {\n box-shadow: inset 0 0 0 1px rgba(32, 32, 32, 0.2);\n}\n@media (hover: hover) {\n .slider__button {\n display: flex;\n }\n}\n.slider__button--hidden {\n display: none;\n}\n.slider__button--next {\n right: 5px;\n}\n.slider__button--prev {\n left: 5px;\n}",".slider {\n position: relative;\n}\n.slider__wrapper {\n overscroll-behavior-x: contain;\n -ms-overflow-style: none;\n scrollbar-width: none;\n display: flex;\n flex-direction: row;\n overflow-x: auto;\n scroll-snap-type: x proximity;\n}\n.slider__wrapper::-webkit-scrollbar {\n display: none;\n}\n@media (hover: hover) {\n .slider__wrapper {\n scroll-snap-type: initial;\n }\n}\n.slider__wrapper:not(.is-dragging) {\n scroll-behavior: smooth;\n}\n.slider__wrapper.is-scrollable {\n cursor: move;\n}\n.slider__wrapper.is-dragging {\n cursor: grabbing;\n user-select: none;\n}\n.slider__wrapper__slide {\n scroll-snap-align: start;\n}"]}
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,149 @@
|
|
|
1
|
-
import { jsxs,
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { useRef, useState, useEffect, useCallback, Children } from 'react';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
var classnamesExports = {};
|
|
5
|
+
var classnames = {
|
|
6
|
+
get exports(){ return classnamesExports; },
|
|
7
|
+
set exports(v){ classnamesExports = v; },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/*!
|
|
11
|
+
Copyright (c) 2018 Jed Watson.
|
|
12
|
+
Licensed under the MIT License (MIT), see
|
|
13
|
+
http://jedwatson.github.io/classnames
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
(function (module) {
|
|
17
|
+
/* global define */
|
|
18
|
+
|
|
19
|
+
(function () {
|
|
20
|
+
|
|
21
|
+
var hasOwn = {}.hasOwnProperty;
|
|
22
|
+
|
|
23
|
+
function classNames() {
|
|
24
|
+
var classes = [];
|
|
25
|
+
|
|
26
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
27
|
+
var arg = arguments[i];
|
|
28
|
+
if (!arg) continue;
|
|
29
|
+
|
|
30
|
+
var argType = typeof arg;
|
|
31
|
+
|
|
32
|
+
if (argType === 'string' || argType === 'number') {
|
|
33
|
+
classes.push(arg);
|
|
34
|
+
} else if (Array.isArray(arg)) {
|
|
35
|
+
if (arg.length) {
|
|
36
|
+
var inner = classNames.apply(null, arg);
|
|
37
|
+
if (inner) {
|
|
38
|
+
classes.push(inner);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} else if (argType === 'object') {
|
|
42
|
+
if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {
|
|
43
|
+
classes.push(arg.toString());
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (var key in arg) {
|
|
48
|
+
if (hasOwn.call(arg, key) && arg[key]) {
|
|
49
|
+
classes.push(key);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return classes.join(' ');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (module.exports) {
|
|
59
|
+
classNames.default = classNames;
|
|
60
|
+
module.exports = classNames;
|
|
61
|
+
} else {
|
|
62
|
+
window.classNames = classNames;
|
|
63
|
+
}
|
|
64
|
+
}());
|
|
65
|
+
} (classnames));
|
|
66
|
+
|
|
67
|
+
var classNames = classnamesExports;
|
|
68
|
+
|
|
69
|
+
const NextButton = ({ onClick, isHidden }) => {
|
|
70
|
+
return (jsx("button", { "aria-label": "Next slide", type: "button", onClick: onClick, "aria-hidden": isHidden, className: classNames([
|
|
71
|
+
'slider__button',
|
|
72
|
+
'slider__button--next',
|
|
73
|
+
{ 'slider__button--hidden': isHidden },
|
|
74
|
+
]), children: jsx("svg", { className: "slider__button__icon", xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 256 256", children: jsx("path", { d: "M96,216a8.5,8.5,0,0,1-5.7-2.3,8.1,8.1,0,0,1,0-11.4L164.7,128,90.3,53.7a8.1,8.1,0,0,1,11.4-11.4l80,80a8.1,8.1,0,0,1,0,11.4l-80,80A8.5,8.5,0,0,1,96,216Z" }) }) }));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const PreviousButton = ({ onClick, isHidden }) => {
|
|
78
|
+
return (jsx("button", { "aria-label": "Previous slide", type: "button", onClick: onClick, "aria-hidden": isHidden, className: classNames([
|
|
79
|
+
'slider__button',
|
|
80
|
+
'slider__button--prev',
|
|
81
|
+
{ 'slider__button--hidden': isHidden },
|
|
82
|
+
]), children: jsx("svg", { className: "slider__button__icon", xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 256 256", children: jsx("path", { d: "M160,216a8.5,8.5,0,0,1-5.7-2.3l-80-80a8.1,8.1,0,0,1,0-11.4l80-80a8.1,8.1,0,0,1,11.4,11.4L91.3,128l74.4,74.3a8.1,8.1,0,0,1,0,11.4A8.5,8.5,0,0,1,160,216Z" }) }) }));
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
var Visibility;
|
|
86
|
+
(function (Visibility) {
|
|
87
|
+
Visibility[Visibility["FULL"] = 0] = "FULL";
|
|
88
|
+
Visibility[Visibility["PARTIAL"] = 1] = "PARTIAL";
|
|
89
|
+
Visibility[Visibility["NONE"] = 2] = "NONE";
|
|
90
|
+
})(Visibility || (Visibility = {}));
|
|
10
91
|
var NavigationDirection;
|
|
11
92
|
(function (NavigationDirection) {
|
|
12
93
|
NavigationDirection[NavigationDirection["PREV"] = 0] = "PREV";
|
|
13
94
|
NavigationDirection[NavigationDirection["NEXT"] = 1] = "NEXT";
|
|
14
95
|
})(NavigationDirection || (NavigationDirection = {}));
|
|
15
|
-
const
|
|
16
|
-
const slides = useRef([]);
|
|
17
|
-
const wrapper = useRef(null);
|
|
96
|
+
const useSlider = () => {
|
|
18
97
|
const visibleSlideIndices = useRef([]);
|
|
19
98
|
const partiallyVisibleSlideIndices = useRef([]);
|
|
99
|
+
const getFirstVisibleSlideIndex = () => visibleSlideIndices.current[0] ?? partiallyVisibleSlideIndices.current[0] ?? -1;
|
|
100
|
+
const getLastVisibleSlideIndex = () => visibleSlideIndices.current[visibleSlideIndices.current.length - 1]
|
|
101
|
+
?? partiallyVisibleSlideIndices.current[partiallyVisibleSlideIndices.current.length - 1] ?? -1;
|
|
102
|
+
const addVisibleSlide = (index) => visibleSlideIndices.current.push(index);
|
|
103
|
+
const addPartiallyVisibleSlide = (index) => partiallyVisibleSlideIndices.current.push(index);
|
|
104
|
+
const removePartiallyVisibleSlide = (index) => partiallyVisibleSlideIndices.current = partiallyVisibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
105
|
+
const removeVisibleSlide = (index) => visibleSlideIndices.current = visibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
106
|
+
const sortSlides = () => {
|
|
107
|
+
visibleSlideIndices.current = [...new Set(visibleSlideIndices.current)].sort((a, b) => a - b);
|
|
108
|
+
partiallyVisibleSlideIndices.current = [...new Set(partiallyVisibleSlideIndices.current)].sort((a, b) => a - b);
|
|
109
|
+
};
|
|
110
|
+
const getLeftPositionToScrollTo = (direction, slideOffsetLeft, wrapperOffsetLeft, wrapperWidth, slideWidth) => {
|
|
111
|
+
let scrollLeft = 0;
|
|
112
|
+
if (direction === NavigationDirection.PREV) {
|
|
113
|
+
scrollLeft = slideOffsetLeft - wrapperOffsetLeft - wrapperWidth + slideWidth;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
scrollLeft = slideOffsetLeft - wrapperOffsetLeft;
|
|
117
|
+
}
|
|
118
|
+
return scrollLeft;
|
|
119
|
+
};
|
|
120
|
+
const getVisibilityByIntersectionRatio = (intersectionRatio) => {
|
|
121
|
+
if (intersectionRatio >= 0.9) {
|
|
122
|
+
return Visibility.FULL;
|
|
123
|
+
}
|
|
124
|
+
if (intersectionRatio >= 0.5) {
|
|
125
|
+
return Visibility.PARTIAL;
|
|
126
|
+
}
|
|
127
|
+
return Visibility.NONE;
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
addVisibleSlide,
|
|
131
|
+
addPartiallyVisibleSlide,
|
|
132
|
+
removePartiallyVisibleSlide,
|
|
133
|
+
removeVisibleSlide,
|
|
134
|
+
sortSlides,
|
|
135
|
+
getFirstVisibleSlideIndex,
|
|
136
|
+
getLastVisibleSlideIndex,
|
|
137
|
+
getLeftPositionToScrollTo,
|
|
138
|
+
getVisibilityByIntersectionRatio,
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const Slider = ({ children, hideNavigationButtons = false }) => {
|
|
143
|
+
const slides = useRef([]);
|
|
144
|
+
const wrapper = useRef(null);
|
|
145
|
+
const [nextArrowVisible, setNextArrowVisible] = useState(false);
|
|
146
|
+
const [prevArrowVisible, setPrevArrowVisible] = useState(false);
|
|
20
147
|
const [isScrollable, setIsScrollable] = useState(false);
|
|
21
148
|
const [isDragging, setIsDragging] = useState(false);
|
|
22
149
|
const [isBlockingClicks, setIsBlockingClicks] = useState(false);
|
|
@@ -24,14 +151,13 @@ const Slider = ({ children }) => {
|
|
|
24
151
|
clientX: 0,
|
|
25
152
|
scrollX: 0,
|
|
26
153
|
});
|
|
27
|
-
const
|
|
28
|
-
const arrowNextRef = useRef(null);
|
|
154
|
+
const { getLeftPositionToScrollTo, getVisibilityByIntersectionRatio, addVisibleSlide, addPartiallyVisibleSlide, getLastVisibleSlideIndex, sortSlides, getFirstVisibleSlideIndex, removeVisibleSlide, removePartiallyVisibleSlide, } = useSlider();
|
|
29
155
|
useEffect(() => {
|
|
30
156
|
const currentWrapper = wrapper.current;
|
|
31
157
|
if (!currentWrapper) {
|
|
32
158
|
return () => { };
|
|
33
159
|
}
|
|
34
|
-
const checkScrollable = () => setIsScrollable(currentWrapper.
|
|
160
|
+
const checkScrollable = () => setIsScrollable(currentWrapper.scrollWidth > currentWrapper.clientWidth);
|
|
35
161
|
window?.addEventListener('resize', checkScrollable);
|
|
36
162
|
checkScrollable();
|
|
37
163
|
return () => {
|
|
@@ -39,10 +165,6 @@ const Slider = ({ children }) => {
|
|
|
39
165
|
};
|
|
40
166
|
}, [wrapper]);
|
|
41
167
|
useEffect(() => {
|
|
42
|
-
wrapper.current?.classList.toggle('is-scrollable', isScrollable);
|
|
43
|
-
}, [isScrollable]);
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
wrapper.current?.classList.toggle('is-dragging', isDragging);
|
|
46
168
|
const onDocumentMouseUp = (event) => {
|
|
47
169
|
event.stopPropagation();
|
|
48
170
|
event.preventDefault();
|
|
@@ -63,9 +185,7 @@ const Slider = ({ children }) => {
|
|
|
63
185
|
}
|
|
64
186
|
setIsBlockingClicks(false);
|
|
65
187
|
};
|
|
66
|
-
const mouseUpHandler = () =>
|
|
67
|
-
setIsDragging(false);
|
|
68
|
-
};
|
|
188
|
+
const mouseUpHandler = () => setIsDragging(false);
|
|
69
189
|
const mouseDownHandler = (event) => {
|
|
70
190
|
setMousePosition({
|
|
71
191
|
...mousePosition,
|
|
@@ -86,57 +206,30 @@ const Slider = ({ children }) => {
|
|
|
86
206
|
const addSlide = (node, index) => {
|
|
87
207
|
slides.current[index] = {
|
|
88
208
|
element: node,
|
|
89
|
-
visibility:
|
|
209
|
+
visibility: Visibility.NONE,
|
|
90
210
|
};
|
|
91
211
|
};
|
|
92
|
-
const getFirstVisibleSlideIndex = () => visibleSlideIndices.current[0] ?? partiallyVisibleSlideIndices.current[0] ?? -1;
|
|
93
|
-
const getLastVisibleSlideIndex = () => visibleSlideIndices.current[visibleSlideIndices.current.length - 1]
|
|
94
|
-
?? partiallyVisibleSlideIndices.current[partiallyVisibleSlideIndices.current.length - 1] ?? -1;
|
|
95
212
|
const setControlsVisibility = useCallback(() => {
|
|
96
213
|
const lastSlideFullyVisible = getLastVisibleSlideIndex() + 1 === slides.current.length;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
arrowNextRef.current.classList.toggle('slider__button--hidden', moreContentAvailable === false);
|
|
101
|
-
arrowNextRef.current.ariaHidden = String(moreContentAvailable === false);
|
|
102
|
-
arrowPrevRef.current.classList.toggle('slider__button--hidden', previousContentAvailable === false);
|
|
103
|
-
arrowPrevRef.current.ariaHidden = String(previousContentAvailable === false);
|
|
104
|
-
}
|
|
105
|
-
}, [isScrollable]);
|
|
106
|
-
const getVisibilityByIntersectionRatio = (intersectionRatio) => {
|
|
107
|
-
if (intersectionRatio >= 0.9) {
|
|
108
|
-
return Visbility.FULL;
|
|
109
|
-
}
|
|
110
|
-
if (intersectionRatio >= 0.5) {
|
|
111
|
-
return Visbility.PARTIAL;
|
|
112
|
-
}
|
|
113
|
-
return Visbility.NONE;
|
|
114
|
-
};
|
|
214
|
+
setPrevArrowVisible(getFirstVisibleSlideIndex() > 0 && isScrollable);
|
|
215
|
+
setNextArrowVisible(isScrollable && lastSlideFullyVisible === false);
|
|
216
|
+
}, [getFirstVisibleSlideIndex, getLastVisibleSlideIndex, isScrollable]);
|
|
115
217
|
useEffect(() => {
|
|
116
218
|
if (!wrapper.current) {
|
|
117
219
|
return () => { };
|
|
118
220
|
}
|
|
119
|
-
setControlsVisibility();
|
|
120
221
|
const intersectionCallback = (entries) => {
|
|
121
222
|
entries.forEach((entry) => {
|
|
122
223
|
const target = entry.target;
|
|
123
224
|
const index = Number(target.dataset.slideIndex);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
else {
|
|
128
|
-
visibleSlideIndices.current = visibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
129
|
-
}
|
|
130
|
-
if (getVisibilityByIntersectionRatio(entry.intersectionRatio) === Visbility.PARTIAL) {
|
|
131
|
-
partiallyVisibleSlideIndices.current.push(index);
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
partiallyVisibleSlideIndices.current = partiallyVisibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
135
|
-
}
|
|
225
|
+
const visibility = getVisibilityByIntersectionRatio(entry.intersectionRatio);
|
|
226
|
+
visibility === Visibility.FULL ? addVisibleSlide(index) : removeVisibleSlide(index);
|
|
227
|
+
visibility === Visibility.PARTIAL ? addPartiallyVisibleSlide(index) : removePartiallyVisibleSlide(index);
|
|
136
228
|
});
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
229
|
+
sortSlides();
|
|
230
|
+
if (hideNavigationButtons === false) {
|
|
231
|
+
setControlsVisibility();
|
|
232
|
+
}
|
|
140
233
|
};
|
|
141
234
|
const intersectionObserver = new IntersectionObserver(intersectionCallback, {
|
|
142
235
|
root: wrapper.current,
|
|
@@ -144,28 +237,35 @@ const Slider = ({ children }) => {
|
|
|
144
237
|
});
|
|
145
238
|
slides.current.forEach(({ element }) => intersectionObserver.observe(element));
|
|
146
239
|
return () => intersectionObserver.disconnect();
|
|
147
|
-
}, [
|
|
240
|
+
}, [
|
|
241
|
+
wrapper,
|
|
242
|
+
setControlsVisibility,
|
|
243
|
+
hideNavigationButtons,
|
|
244
|
+
sortSlides,
|
|
245
|
+
addVisibleSlide,
|
|
246
|
+
removeVisibleSlide,
|
|
247
|
+
addPartiallyVisibleSlide,
|
|
248
|
+
removePartiallyVisibleSlide,
|
|
249
|
+
getVisibilityByIntersectionRatio,
|
|
250
|
+
]);
|
|
148
251
|
const navigate = (direction) => {
|
|
149
252
|
if (!wrapper.current) {
|
|
150
253
|
return;
|
|
151
254
|
}
|
|
152
255
|
const targetSlideIndex = direction === NavigationDirection.PREV ? getFirstVisibleSlideIndex() - 1 : getLastVisibleSlideIndex() + 1;
|
|
153
256
|
const targetSlide = slides.current[targetSlideIndex];
|
|
154
|
-
let scrollLeft = 0;
|
|
155
257
|
if (!targetSlide) {
|
|
156
258
|
return;
|
|
157
259
|
}
|
|
158
|
-
|
|
159
|
-
scrollLeft = targetSlide.element.offsetLeft - wrapper.current.offsetLeft - wrapper.current.clientWidth + targetSlide.element.clientWidth;
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
scrollLeft = targetSlide.element.offsetLeft - wrapper.current.offsetLeft;
|
|
163
|
-
}
|
|
260
|
+
const scrollLeft = getLeftPositionToScrollTo(direction, targetSlide.element.offsetLeft, wrapper.current.offsetLeft, wrapper.current.clientWidth, targetSlide.element.clientWidth);
|
|
164
261
|
wrapper.current.scrollTo({ behavior: 'smooth', left: scrollLeft, top: 0 });
|
|
165
262
|
};
|
|
166
|
-
return (jsxs("div", { className: "slider", children: [jsx("div", {
|
|
263
|
+
return (jsxs("div", { className: "slider", children: [jsx("div", { role: "list", ref: wrapper, onMouseDown: mouseDownHandler, onMouseMove: mouseMoveHandler, onMouseUp: mouseUpHandler, onClickCapture: blockChildClickHandler, className: classNames('slider__wrapper', {
|
|
264
|
+
'is-scrollable': isScrollable,
|
|
265
|
+
'is-dragging': isDragging,
|
|
266
|
+
}), children: Children.map(children, (child, index) => (jsx("div", { className: "slider__wrapper__slide", role: "listitem", "data-slide-index": index, ref: (node) => { if (node) {
|
|
167
267
|
addSlide(node, index);
|
|
168
|
-
} }, children: child }, index))) }),
|
|
268
|
+
} }, children: child }, index))) }), hideNavigationButtons === false && (jsxs(Fragment, { children: [jsx(PreviousButton, { onClick: () => navigate(NavigationDirection.PREV), isHidden: prevArrowVisible === false }), jsx(NextButton, { onClick: () => navigate(NavigationDirection.NEXT), isHidden: nextArrowVisible === false })] }))] }));
|
|
169
269
|
};
|
|
170
270
|
|
|
171
271
|
export { Slider };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/Slider.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../node_modules/classnames/index.js","../src/Components/Controls/NextButton.tsx","../src/Components/Controls/PreviousButton.tsx","../src/Hooks/UseSlider.ts","../src/Slider.tsx"],"sourcesContent":["/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\tvar nativeCodeString = '[native code]';\n\n\tfunction classNames() {\n\t\tvar classes = [];\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (!arg) continue;\n\n\t\t\tvar argType = typeof arg;\n\n\t\t\tif (argType === 'string' || argType === 'number') {\n\t\t\t\tclasses.push(arg);\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tif (arg.length) {\n\t\t\t\t\tvar inner = classNames.apply(null, arg);\n\t\t\t\t\tif (inner) {\n\t\t\t\t\t\tclasses.push(inner);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (argType === 'object') {\n\t\t\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\t\t\tclasses.push(arg.toString());\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfor (var key in arg) {\n\t\t\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\t\t\tclasses.push(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn classes.join(' ');\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n",null,null,null,null],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yoursurprise/slider",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"description": "Basic React slider using modern Javascript and CSS",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"serve": "parcel index.html",
|
|
23
23
|
"deploy-pages": "gh-pages -d dist"
|
|
24
24
|
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"classnames": "^2.3.2"
|
|
27
|
+
},
|
|
25
28
|
"peerDependencies": {
|
|
26
29
|
"react": "^18.2.0",
|
|
27
30
|
"react-dom": "^18.2.0"
|
|
@@ -56,6 +59,7 @@
|
|
|
56
59
|
"npm": "^8.19.3",
|
|
57
60
|
"parcel": "^2.8.3",
|
|
58
61
|
"postcss": "^8.4.18",
|
|
62
|
+
"process": "^0.11.10",
|
|
59
63
|
"react": "^18.2.0",
|
|
60
64
|
"react-dom": "^18.2.0",
|
|
61
65
|
"react-test-renderer": "^18.2.0",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
.slider__button {
|
|
2
|
+
position: absolute;
|
|
3
|
+
top: 0;
|
|
4
|
+
bottom: 0;
|
|
5
|
+
height: 48px;
|
|
6
|
+
width: 48px;
|
|
7
|
+
margin: auto 0;
|
|
8
|
+
border-radius: 50%;
|
|
9
|
+
background-color: white;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: center;
|
|
12
|
+
cursor: pointer;
|
|
13
|
+
display: none;
|
|
14
|
+
border: none;
|
|
15
|
+
outline: none;
|
|
16
|
+
box-shadow: inset 0 0 0 1px rgba(32, 32, 32, .1);
|
|
17
|
+
transition: box-shadow .2s ease-in-out;
|
|
18
|
+
|
|
19
|
+
&__icon {
|
|
20
|
+
fill: #554c44;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&:hover {
|
|
24
|
+
box-shadow: inset 0 0 0 1px rgba(32, 32, 32, .2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@media (hover: hover) {
|
|
28
|
+
display: flex;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&--hidden {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&--next {
|
|
36
|
+
right: 5px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&--prev {
|
|
40
|
+
left: 5px;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import './Button.scss';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
isHidden: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const NextButton: React.FC<Props> = ({ onClick, isHidden }) => {
|
|
11
|
+
return (
|
|
12
|
+
<button
|
|
13
|
+
aria-label="Next slide"
|
|
14
|
+
type="button"
|
|
15
|
+
onClick={onClick}
|
|
16
|
+
aria-hidden={isHidden}
|
|
17
|
+
className={classNames([
|
|
18
|
+
'slider__button',
|
|
19
|
+
'slider__button--next',
|
|
20
|
+
{ 'slider__button--hidden': isHidden },
|
|
21
|
+
])}
|
|
22
|
+
>
|
|
23
|
+
<svg className="slider__button__icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 256 256">
|
|
24
|
+
<path d="M96,216a8.5,8.5,0,0,1-5.7-2.3,8.1,8.1,0,0,1,0-11.4L164.7,128,90.3,53.7a8.1,8.1,0,0,1,11.4-11.4l80,80a8.1,8.1,0,0,1,0,11.4l-80,80A8.5,8.5,0,0,1,96,216Z"/>
|
|
25
|
+
</svg>
|
|
26
|
+
</button>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import './Button.scss';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
isHidden: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const PreviousButton: React.FC<Props> = ({ onClick, isHidden }) => {
|
|
11
|
+
return (
|
|
12
|
+
<button
|
|
13
|
+
aria-label="Previous slide"
|
|
14
|
+
type="button"
|
|
15
|
+
onClick={onClick}
|
|
16
|
+
aria-hidden={isHidden}
|
|
17
|
+
className={classNames([
|
|
18
|
+
'slider__button',
|
|
19
|
+
'slider__button--prev',
|
|
20
|
+
{ 'slider__button--hidden': isHidden },
|
|
21
|
+
])}
|
|
22
|
+
>
|
|
23
|
+
<svg className="slider__button__icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 256 256">
|
|
24
|
+
<path d="M160,216a8.5,8.5,0,0,1-5.7-2.3l-80-80a8.1,8.1,0,0,1,0-11.4l80-80a8.1,8.1,0,0,1,11.4,11.4L91.3,128l74.4,74.3a8.1,8.1,0,0,1,0,11.4A8.5,8.5,0,0,1,160,216Z"/>
|
|
25
|
+
</svg>
|
|
26
|
+
</button>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { NavigationDirection, useSlider, Visibility } from './UseSlider';
|
|
2
|
+
import { renderHook } from '@testing-library/react';
|
|
3
|
+
|
|
4
|
+
describe('UseSlider', () => {
|
|
5
|
+
describe('keeps track of slides', () => {
|
|
6
|
+
it('gets the first fully visible slide', () => {
|
|
7
|
+
const { result } = renderHook(() => useSlider());
|
|
8
|
+
|
|
9
|
+
result.current.addPartiallyVisibleSlide(1);
|
|
10
|
+
result.current.addVisibleSlide(2);
|
|
11
|
+
result.current.addVisibleSlide(3);
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
expect(result.current.getFirstVisibleSlideIndex()).toBe(2);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('gets the last fully visible slide', () => {
|
|
18
|
+
const { result } = renderHook(() => useSlider());
|
|
19
|
+
|
|
20
|
+
result.current.addVisibleSlide(1);
|
|
21
|
+
result.current.addVisibleSlide(2);
|
|
22
|
+
result.current.addPartiallyVisibleSlide(3);
|
|
23
|
+
|
|
24
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(2);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
it('gets the first partially visible slide when no slide is fully visible', () => {
|
|
29
|
+
const { result } = renderHook(() => useSlider());
|
|
30
|
+
|
|
31
|
+
result.current.addPartiallyVisibleSlide(1);
|
|
32
|
+
result.current.addPartiallyVisibleSlide(2);
|
|
33
|
+
|
|
34
|
+
expect(result.current.getFirstVisibleSlideIndex()).toBe(1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('gets the last visible slide when no slide is fully visible', () => {
|
|
38
|
+
const { result } = renderHook(() => useSlider());
|
|
39
|
+
|
|
40
|
+
result.current.addPartiallyVisibleSlide(1);
|
|
41
|
+
result.current.addPartiallyVisibleSlide(2);
|
|
42
|
+
|
|
43
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(2);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
it('falls back when first slide is non-existant', () => {
|
|
48
|
+
const { result } = renderHook(() => useSlider());
|
|
49
|
+
expect(result.current.getFirstVisibleSlideIndex()).toBe(-1);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
it('falls back when last slide is non-existant', () => {
|
|
54
|
+
const { result } = renderHook(() => useSlider());
|
|
55
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(-1);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('sorts the fully visible slides by index', () => {
|
|
59
|
+
const { result } = renderHook(() => useSlider());
|
|
60
|
+
|
|
61
|
+
result.current.addVisibleSlide(3);
|
|
62
|
+
result.current.addVisibleSlide(2);
|
|
63
|
+
result.current.addVisibleSlide(1);
|
|
64
|
+
|
|
65
|
+
expect(result.current.getFirstVisibleSlideIndex()).toBe(3);
|
|
66
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(1);
|
|
67
|
+
|
|
68
|
+
result.current.sortSlides();
|
|
69
|
+
|
|
70
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(3);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('sorts the partially fully visible slides by index', () => {
|
|
74
|
+
const { result } = renderHook(() => useSlider());
|
|
75
|
+
|
|
76
|
+
result.current.addPartiallyVisibleSlide(3);
|
|
77
|
+
result.current.addPartiallyVisibleSlide(2);
|
|
78
|
+
result.current.addPartiallyVisibleSlide(1);
|
|
79
|
+
|
|
80
|
+
expect(result.current.getFirstVisibleSlideIndex()).toBe(3);
|
|
81
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(1);
|
|
82
|
+
|
|
83
|
+
result.current.sortSlides();
|
|
84
|
+
|
|
85
|
+
expect(result.current.getLastVisibleSlideIndex()).toBe(3);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('calculations', () => {
|
|
90
|
+
|
|
91
|
+
it('calculates the scrollLeft position (next)', () => {
|
|
92
|
+
const { result } = renderHook(() => useSlider());
|
|
93
|
+
|
|
94
|
+
expect(result.current.getLeftPositionToScrollTo(NavigationDirection.NEXT, 200, 50, 1250, 325)).toBe(150);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('calculates the scrollLeft position (prev)', () => {
|
|
98
|
+
const { result } = renderHook(() => useSlider());
|
|
99
|
+
|
|
100
|
+
expect(result.current.getLeftPositionToScrollTo(NavigationDirection.PREV, 875, 50, 1250, 325)).toBe(-100);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('calculates the visibility of a slide', () => {
|
|
104
|
+
const { result } = renderHook(() => useSlider());
|
|
105
|
+
|
|
106
|
+
[
|
|
107
|
+
[0.0, Visibility.NONE],
|
|
108
|
+
[0.1, Visibility.NONE],
|
|
109
|
+
[0.2, Visibility.NONE],
|
|
110
|
+
[0.3, Visibility.NONE],
|
|
111
|
+
[0.4, Visibility.NONE],
|
|
112
|
+
[0.5, Visibility.PARTIAL],
|
|
113
|
+
[0.6, Visibility.PARTIAL],
|
|
114
|
+
[0.7, Visibility.PARTIAL],
|
|
115
|
+
[0.8, Visibility.PARTIAL],
|
|
116
|
+
[0.9, Visibility.FULL],
|
|
117
|
+
[1.0, Visibility.FULL],
|
|
118
|
+
].forEach(([ratio, expectation]) => {
|
|
119
|
+
expect(result.current.getVisibilityByIntersectionRatio(ratio)).toBe(expectation);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export enum Visibility {
|
|
4
|
+
FULL,
|
|
5
|
+
PARTIAL,
|
|
6
|
+
NONE,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export enum NavigationDirection {
|
|
10
|
+
PREV,
|
|
11
|
+
NEXT,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface UseSlider {
|
|
15
|
+
getLeftPositionToScrollTo: (direction: NavigationDirection, slideOffsetLeft: number, wrapperOffsetLeft: number, wrapperWidth: number, slideWidth: number) => number;
|
|
16
|
+
getVisibilityByIntersectionRatio: (intersectionRatio: number) => Visibility;
|
|
17
|
+
getFirstVisibleSlideIndex: () => number;
|
|
18
|
+
getLastVisibleSlideIndex: () => number;
|
|
19
|
+
addVisibleSlide: (index: number) => void;
|
|
20
|
+
addPartiallyVisibleSlide: (index: number) => void;
|
|
21
|
+
sortSlides: () => void;
|
|
22
|
+
removeVisibleSlide: (index: number) => void;
|
|
23
|
+
removePartiallyVisibleSlide: (index: number) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const useSlider = (): UseSlider => {
|
|
27
|
+
const visibleSlideIndices = useRef<number[]>([]);
|
|
28
|
+
const partiallyVisibleSlideIndices = useRef<number[]>([]);
|
|
29
|
+
|
|
30
|
+
const getFirstVisibleSlideIndex = (): number => visibleSlideIndices.current[0] ?? partiallyVisibleSlideIndices.current[0] ?? -1;
|
|
31
|
+
|
|
32
|
+
const getLastVisibleSlideIndex = (): number => visibleSlideIndices.current[visibleSlideIndices.current.length - 1]
|
|
33
|
+
?? partiallyVisibleSlideIndices.current[partiallyVisibleSlideIndices.current.length - 1] ?? -1;
|
|
34
|
+
|
|
35
|
+
const addVisibleSlide = (index: number) => visibleSlideIndices.current.push(index);
|
|
36
|
+
|
|
37
|
+
const addPartiallyVisibleSlide = (index: number) => partiallyVisibleSlideIndices.current.push(index);
|
|
38
|
+
|
|
39
|
+
const removePartiallyVisibleSlide = (index: number) => partiallyVisibleSlideIndices.current = partiallyVisibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
40
|
+
|
|
41
|
+
const removeVisibleSlide = (index: number) => visibleSlideIndices.current = visibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
42
|
+
|
|
43
|
+
const sortSlides = () => {
|
|
44
|
+
// Make sure there are no duplicate visible slides, then sort to retain proper order
|
|
45
|
+
visibleSlideIndices.current = [...new Set(visibleSlideIndices.current)].sort((a, b) => a - b);
|
|
46
|
+
partiallyVisibleSlideIndices.current = [...new Set(partiallyVisibleSlideIndices.current)].sort((a, b) => a - b);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const getLeftPositionToScrollTo = (direction: NavigationDirection, slideOffsetLeft: number, wrapperOffsetLeft: number, wrapperWidth: number, slideWidth: number) => {
|
|
50
|
+
let scrollLeft = 0;
|
|
51
|
+
|
|
52
|
+
if (direction === NavigationDirection.PREV) {
|
|
53
|
+
scrollLeft = slideOffsetLeft - wrapperOffsetLeft - wrapperWidth + slideWidth;
|
|
54
|
+
} else {
|
|
55
|
+
scrollLeft = slideOffsetLeft - wrapperOffsetLeft;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return scrollLeft;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const getVisibilityByIntersectionRatio = (intersectionRatio: number) => {
|
|
62
|
+
if (intersectionRatio >= 0.9) {
|
|
63
|
+
return Visibility.FULL;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (intersectionRatio >= 0.5) {
|
|
67
|
+
return Visibility.PARTIAL;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return Visibility.NONE;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
addVisibleSlide,
|
|
75
|
+
addPartiallyVisibleSlide,
|
|
76
|
+
removePartiallyVisibleSlide,
|
|
77
|
+
removeVisibleSlide,
|
|
78
|
+
sortSlides,
|
|
79
|
+
getFirstVisibleSlideIndex,
|
|
80
|
+
getLastVisibleSlideIndex,
|
|
81
|
+
getLeftPositionToScrollTo,
|
|
82
|
+
getVisibilityByIntersectionRatio,
|
|
83
|
+
};
|
|
84
|
+
};
|
package/src/Slider.scss
CHANGED
|
@@ -1,43 +1,6 @@
|
|
|
1
1
|
.slider {
|
|
2
2
|
position: relative;
|
|
3
3
|
|
|
4
|
-
&__button {
|
|
5
|
-
position: absolute;
|
|
6
|
-
top: 0;
|
|
7
|
-
bottom: 0;
|
|
8
|
-
|
|
9
|
-
height: 48px;
|
|
10
|
-
width: 48px;
|
|
11
|
-
margin: auto 0;
|
|
12
|
-
border-radius: 50%;
|
|
13
|
-
|
|
14
|
-
border: 1px solid #C9C9C9;
|
|
15
|
-
background-color: white;
|
|
16
|
-
|
|
17
|
-
align-items: center;
|
|
18
|
-
justify-content: center;
|
|
19
|
-
|
|
20
|
-
cursor: pointer;
|
|
21
|
-
|
|
22
|
-
display: none;
|
|
23
|
-
|
|
24
|
-
@media (hover: hover) {
|
|
25
|
-
display: flex;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
&--hidden {
|
|
29
|
-
display: none;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
&--next {
|
|
33
|
-
right: 5px;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
&--prev {
|
|
37
|
-
left: 5px;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
4
|
&__wrapper {
|
|
42
5
|
|
|
43
6
|
// Prevent the browser from going back in history when there is no scroll area left
|
package/src/Slider.test.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fireEvent, render, screen } from '@testing-library/react';
|
|
1
|
+
import { act, fireEvent, render, screen } from '@testing-library/react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
4
|
import { Slider } from './Slider';
|
|
@@ -89,8 +89,23 @@ describe('UpsellSlider', () => {
|
|
|
89
89
|
const nextButton = screen.getByLabelText('Next slide');
|
|
90
90
|
const prevButton = screen.getByLabelText('Previous slide');
|
|
91
91
|
|
|
92
|
-
expect(prevButton
|
|
93
|
-
expect(nextButton
|
|
92
|
+
expect(prevButton).toHaveAttribute('aria-hidden', 'true');
|
|
93
|
+
expect(nextButton).toHaveAttribute('aria-hidden', 'true');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('does not render controls if disabled', () => {
|
|
97
|
+
render(<Slider hideNavigationButtons={true}>
|
|
98
|
+
<span key={1}/>
|
|
99
|
+
<span key={2}/>
|
|
100
|
+
<span key={3}/>
|
|
101
|
+
<span key={4}/>
|
|
102
|
+
</Slider>);
|
|
103
|
+
|
|
104
|
+
const nextButton = screen.queryByLabelText('Next slide');
|
|
105
|
+
const prevButton = screen.queryByLabelText('Previous slide');
|
|
106
|
+
|
|
107
|
+
expect(prevButton).not.toBeInTheDocument();
|
|
108
|
+
expect(nextButton).not.toBeInTheDocument();
|
|
94
109
|
});
|
|
95
110
|
|
|
96
111
|
it('allows scrolling by dragging with the mouse', () => {
|
|
@@ -164,12 +179,14 @@ describe('UpsellSlider', () => {
|
|
|
164
179
|
Object.defineProperty(child, 'offsetLeft', { value: 100 * (i + 1) });
|
|
165
180
|
});
|
|
166
181
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
182
|
+
await act(() => {
|
|
183
|
+
intersectionCallback([
|
|
184
|
+
{ intersectionRatio: 1, target: slides[ 0 ] } as unknown as IntersectionObserverEntry,
|
|
185
|
+
{ intersectionRatio: 0.5, target: slides[ 1 ] } as unknown as IntersectionObserverEntry,
|
|
186
|
+
{ intersectionRatio: 0, target: slides[ 2 ] } as unknown as IntersectionObserverEntry,
|
|
187
|
+
{ intersectionRatio: 0, target: slides[ 3 ] } as unknown as IntersectionObserverEntry,
|
|
188
|
+
]);
|
|
189
|
+
});
|
|
173
190
|
|
|
174
191
|
await userEvent.click(nextButton);
|
|
175
192
|
|
|
@@ -191,12 +208,14 @@ describe('UpsellSlider', () => {
|
|
|
191
208
|
Object.defineProperty(child, 'offsetLeft', { value: 100 * (i + 1) });
|
|
192
209
|
});
|
|
193
210
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
211
|
+
await act(() => {
|
|
212
|
+
intersectionCallback([
|
|
213
|
+
{ intersectionRatio: 0, target: slides[ 0 ] } as unknown as IntersectionObserverEntry,
|
|
214
|
+
{ intersectionRatio: 0, target: slides[ 1 ] } as unknown as IntersectionObserverEntry,
|
|
215
|
+
{ intersectionRatio: 1, target: slides[ 2 ] } as unknown as IntersectionObserverEntry,
|
|
216
|
+
{ intersectionRatio: 0.5, target: slides[ 3 ] } as unknown as IntersectionObserverEntry,
|
|
217
|
+
]);
|
|
218
|
+
});
|
|
200
219
|
|
|
201
220
|
await userEvent.click(prevButton);
|
|
202
221
|
|
|
@@ -207,7 +226,7 @@ describe('UpsellSlider', () => {
|
|
|
207
226
|
});
|
|
208
227
|
});
|
|
209
228
|
|
|
210
|
-
it('updates controls visibility', () => {
|
|
229
|
+
it('updates controls visibility', async () => {
|
|
211
230
|
Object.defineProperty(HTMLElement.prototype, 'clientWidth', { configurable: true, value: 500 });
|
|
212
231
|
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', { configurable: true, value: 1000 });
|
|
213
232
|
Object.defineProperty(HTMLElement.prototype, 'scrollLeft', { configurable: true, value: 0, writable: true });
|
|
@@ -223,26 +242,33 @@ describe('UpsellSlider', () => {
|
|
|
223
242
|
const nextButton = screen.getByLabelText('Next slide');
|
|
224
243
|
const prevButton = screen.getByLabelText('Previous slide');
|
|
225
244
|
|
|
226
|
-
|
|
245
|
+
const testCases = [
|
|
227
246
|
// All slides are visible
|
|
228
247
|
[[1, 1, 1, 1], true, true],
|
|
229
248
|
// Only the first slide is not visible
|
|
230
249
|
[[0, 1, 1, 1], false, true],
|
|
231
250
|
// Only the last slide is not visible
|
|
232
251
|
[[1, 1, 1, 0], true, false],
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
252
|
+
// Only a single slide is partially visible
|
|
253
|
+
[[0, 0, 0.5, 0], false, false],
|
|
254
|
+
] as Array<[number[], boolean, boolean]>;
|
|
255
|
+
|
|
256
|
+
for (const testCase of testCases) {
|
|
257
|
+
const [intersections, prevButtonHidden, nextButtonHidden] = testCase;
|
|
258
|
+
|
|
259
|
+
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
260
|
+
await act(() => {
|
|
261
|
+
intersectionCallback([
|
|
262
|
+
{ intersectionRatio: intersections[0], target: slides[0] } as unknown as IntersectionObserverEntry,
|
|
263
|
+
{ intersectionRatio: intersections[1], target: slides[1] } as unknown as IntersectionObserverEntry,
|
|
264
|
+
{ intersectionRatio: intersections[2], target: slides[2] } as unknown as IntersectionObserverEntry,
|
|
265
|
+
{ intersectionRatio: intersections[3], target: slides[3] } as unknown as IntersectionObserverEntry,
|
|
266
|
+
]);
|
|
267
|
+
});
|
|
242
268
|
|
|
243
|
-
expect(prevButton
|
|
244
|
-
expect(nextButton
|
|
245
|
-
}
|
|
269
|
+
expect(prevButton).toHaveAttribute('aria-hidden', String(prevButtonHidden));
|
|
270
|
+
expect(nextButton).toHaveAttribute('aria-hidden', String(nextButtonHidden));
|
|
271
|
+
}
|
|
246
272
|
});
|
|
247
273
|
});
|
|
248
274
|
});
|
package/src/Slider.tsx
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
1
2
|
import type React from 'react';
|
|
2
3
|
import type { MouseEvent as ReactMouseEvent, PropsWithChildren } from 'react';
|
|
3
4
|
import { useRef, useEffect, Children, useCallback, useState } from 'react';
|
|
5
|
+
import { NextButton } from './Components/Controls/NextButton';
|
|
6
|
+
import { PreviousButton } from './Components/Controls/PreviousButton';
|
|
7
|
+
import { NavigationDirection, useSlider, Visibility } from './Hooks/UseSlider';
|
|
4
8
|
import './Slider.scss';
|
|
5
9
|
|
|
6
|
-
enum Visbility {
|
|
7
|
-
FULL,
|
|
8
|
-
PARTIAL,
|
|
9
|
-
NONE,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
enum NavigationDirection {
|
|
13
|
-
PREV,
|
|
14
|
-
NEXT,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
10
|
interface SlideVisibilityEntry {
|
|
18
11
|
element: HTMLDivElement;
|
|
19
|
-
visibility:
|
|
12
|
+
visibility: Visibility;
|
|
20
13
|
}
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
interface Settings {
|
|
16
|
+
// Sets whether the navigation buttons (next/prev) are no longer rendered
|
|
17
|
+
hideNavigationButtons?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const Slider: React.FC<PropsWithChildren<Settings>> = ({ children, hideNavigationButtons = false }) => {
|
|
23
21
|
const slides = useRef<SlideVisibilityEntry[]>([]);
|
|
24
22
|
const wrapper = useRef<HTMLDivElement>(null);
|
|
25
|
-
|
|
26
|
-
const
|
|
23
|
+
|
|
24
|
+
const [nextArrowVisible, setNextArrowVisible] = useState<boolean>(false);
|
|
25
|
+
const [prevArrowVisible, setPrevArrowVisible] = useState<boolean>(false);
|
|
27
26
|
|
|
28
27
|
const [isScrollable, setIsScrollable] = useState<boolean>(false);
|
|
29
28
|
const [isDragging, setIsDragging] = useState<boolean>(false);
|
|
@@ -33,8 +32,17 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
33
32
|
scrollX: 0,
|
|
34
33
|
});
|
|
35
34
|
|
|
36
|
-
const
|
|
37
|
-
|
|
35
|
+
const {
|
|
36
|
+
getLeftPositionToScrollTo,
|
|
37
|
+
getVisibilityByIntersectionRatio,
|
|
38
|
+
addVisibleSlide,
|
|
39
|
+
addPartiallyVisibleSlide,
|
|
40
|
+
getLastVisibleSlideIndex,
|
|
41
|
+
sortSlides,
|
|
42
|
+
getFirstVisibleSlideIndex,
|
|
43
|
+
removeVisibleSlide,
|
|
44
|
+
removePartiallyVisibleSlide,
|
|
45
|
+
} = useSlider();
|
|
38
46
|
|
|
39
47
|
useEffect(() => {
|
|
40
48
|
const currentWrapper = wrapper.current;
|
|
@@ -43,7 +51,7 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
43
51
|
return () => {};
|
|
44
52
|
}
|
|
45
53
|
|
|
46
|
-
const checkScrollable = () => setIsScrollable(currentWrapper.
|
|
54
|
+
const checkScrollable = () => setIsScrollable(currentWrapper.scrollWidth > currentWrapper.clientWidth);
|
|
47
55
|
|
|
48
56
|
window?.addEventListener('resize', checkScrollable);
|
|
49
57
|
|
|
@@ -55,12 +63,6 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
55
63
|
}, [wrapper]);
|
|
56
64
|
|
|
57
65
|
useEffect(() => {
|
|
58
|
-
wrapper.current?.classList.toggle('is-scrollable', isScrollable);
|
|
59
|
-
}, [isScrollable]);
|
|
60
|
-
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
wrapper.current?.classList.toggle('is-dragging', isDragging);
|
|
63
|
-
|
|
64
66
|
const onDocumentMouseUp = (event: MouseEvent) => {
|
|
65
67
|
event.stopPropagation();
|
|
66
68
|
event.preventDefault();
|
|
@@ -87,9 +89,7 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
87
89
|
setIsBlockingClicks(false);
|
|
88
90
|
};
|
|
89
91
|
|
|
90
|
-
const mouseUpHandler = () =>
|
|
91
|
-
setIsDragging(false);
|
|
92
|
-
};
|
|
92
|
+
const mouseUpHandler = () => setIsDragging(false);
|
|
93
93
|
|
|
94
94
|
const mouseDownHandler = (event: ReactMouseEvent<HTMLDivElement>) => {
|
|
95
95
|
setMousePosition({
|
|
@@ -116,71 +116,37 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
116
116
|
const addSlide = (node: HTMLDivElement, index: number) => {
|
|
117
117
|
slides.current[index] = {
|
|
118
118
|
element: node,
|
|
119
|
-
visibility:
|
|
119
|
+
visibility: Visibility.NONE,
|
|
120
120
|
};
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
const getFirstVisibleSlideIndex = (): number => visibleSlideIndices.current[0] ?? partiallyVisibleSlideIndices.current[0] ?? -1;
|
|
124
|
-
|
|
125
|
-
const getLastVisibleSlideIndex = (): number => visibleSlideIndices.current[visibleSlideIndices.current.length - 1]
|
|
126
|
-
?? partiallyVisibleSlideIndices.current[partiallyVisibleSlideIndices.current.length - 1] ?? -1;
|
|
127
|
-
|
|
128
123
|
const setControlsVisibility = useCallback(() => {
|
|
129
124
|
const lastSlideFullyVisible = getLastVisibleSlideIndex() + 1 === slides.current.length;
|
|
130
|
-
const moreContentAvailable = isScrollable && lastSlideFullyVisible === false;
|
|
131
|
-
const previousContentAvailable = getFirstVisibleSlideIndex() > 0 && isScrollable;
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
arrowPrevRef.current.classList.toggle('slider__button--hidden', previousContentAvailable === false);
|
|
138
|
-
arrowPrevRef.current.ariaHidden = String(previousContentAvailable === false);
|
|
139
|
-
}
|
|
140
|
-
}, [isScrollable]);
|
|
141
|
-
|
|
142
|
-
const getVisibilityByIntersectionRatio = (intersectionRatio: number) => {
|
|
143
|
-
if (intersectionRatio >= 0.9) {
|
|
144
|
-
return Visbility.FULL;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (intersectionRatio >= 0.5) {
|
|
148
|
-
return Visbility.PARTIAL;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return Visbility.NONE;
|
|
152
|
-
};
|
|
126
|
+
setPrevArrowVisible(getFirstVisibleSlideIndex() > 0 && isScrollable);
|
|
127
|
+
setNextArrowVisible(isScrollable && lastSlideFullyVisible === false);
|
|
128
|
+
}, [getFirstVisibleSlideIndex, getLastVisibleSlideIndex, isScrollable]);
|
|
153
129
|
|
|
154
130
|
useEffect(() => {
|
|
155
131
|
if (!wrapper.current) {
|
|
156
132
|
return () => {};
|
|
157
133
|
}
|
|
158
134
|
|
|
159
|
-
setControlsVisibility();
|
|
160
|
-
|
|
161
135
|
const intersectionCallback = (entries: IntersectionObserverEntry[]) => {
|
|
162
136
|
entries.forEach((entry: IntersectionObserverEntry) => {
|
|
163
137
|
const target = entry.target as HTMLDivElement;
|
|
164
138
|
const index = Number(target.dataset.slideIndex);
|
|
139
|
+
const visibility = getVisibilityByIntersectionRatio(entry.intersectionRatio);
|
|
165
140
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
} else {
|
|
169
|
-
visibleSlideIndices.current = visibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (getVisibilityByIntersectionRatio(entry.intersectionRatio) === Visbility.PARTIAL) {
|
|
173
|
-
partiallyVisibleSlideIndices.current.push(index);
|
|
174
|
-
} else {
|
|
175
|
-
partiallyVisibleSlideIndices.current = partiallyVisibleSlideIndices.current.filter((slideIndex) => slideIndex !== index);
|
|
176
|
-
}
|
|
141
|
+
visibility === Visibility.FULL ? addVisibleSlide(index) : removeVisibleSlide(index);
|
|
142
|
+
visibility === Visibility.PARTIAL ? addPartiallyVisibleSlide(index) : removePartiallyVisibleSlide(index);
|
|
177
143
|
});
|
|
178
144
|
|
|
179
|
-
|
|
180
|
-
visibleSlideIndices.current = [...new Set(visibleSlideIndices.current)].sort((a, b) => a - b);
|
|
181
|
-
partiallyVisibleSlideIndices.current = [...new Set(partiallyVisibleSlideIndices.current)].sort((a, b) => a - b);
|
|
145
|
+
sortSlides();
|
|
182
146
|
|
|
183
|
-
|
|
147
|
+
if (hideNavigationButtons === false) {
|
|
148
|
+
setControlsVisibility();
|
|
149
|
+
}
|
|
184
150
|
};
|
|
185
151
|
|
|
186
152
|
const intersectionObserver = new IntersectionObserver(intersectionCallback, {
|
|
@@ -191,7 +157,17 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
191
157
|
slides.current.forEach(({ element }) => intersectionObserver.observe(element));
|
|
192
158
|
|
|
193
159
|
return () => intersectionObserver.disconnect();
|
|
194
|
-
}, [
|
|
160
|
+
}, [
|
|
161
|
+
wrapper,
|
|
162
|
+
setControlsVisibility,
|
|
163
|
+
hideNavigationButtons,
|
|
164
|
+
sortSlides,
|
|
165
|
+
addVisibleSlide,
|
|
166
|
+
removeVisibleSlide,
|
|
167
|
+
addPartiallyVisibleSlide,
|
|
168
|
+
removePartiallyVisibleSlide,
|
|
169
|
+
getVisibilityByIntersectionRatio,
|
|
170
|
+
]);
|
|
195
171
|
|
|
196
172
|
const navigate = (direction: NavigationDirection) => {
|
|
197
173
|
if (!wrapper.current) {
|
|
@@ -199,30 +175,34 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
199
175
|
}
|
|
200
176
|
|
|
201
177
|
const targetSlideIndex = direction === NavigationDirection.PREV ? getFirstVisibleSlideIndex() - 1 : getLastVisibleSlideIndex() + 1;
|
|
202
|
-
|
|
203
178
|
const targetSlide = slides.current[targetSlideIndex];
|
|
204
|
-
let scrollLeft = 0;
|
|
205
179
|
|
|
206
180
|
if (!targetSlide) {
|
|
207
181
|
return;
|
|
208
182
|
}
|
|
209
183
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
184
|
+
const scrollLeft = getLeftPositionToScrollTo(
|
|
185
|
+
direction,
|
|
186
|
+
targetSlide.element.offsetLeft,
|
|
187
|
+
wrapper.current.offsetLeft,
|
|
188
|
+
wrapper.current.clientWidth,
|
|
189
|
+
targetSlide.element.clientWidth,
|
|
190
|
+
);
|
|
215
191
|
|
|
216
192
|
wrapper.current.scrollTo({ behavior: 'smooth', left: scrollLeft, top: 0 });
|
|
217
193
|
};
|
|
218
194
|
|
|
219
195
|
return (
|
|
220
196
|
<div className="slider">
|
|
221
|
-
<div
|
|
197
|
+
<div role="list" ref={wrapper}
|
|
222
198
|
onMouseDown={mouseDownHandler}
|
|
223
199
|
onMouseMove={mouseMoveHandler}
|
|
224
200
|
onMouseUp={mouseUpHandler}
|
|
225
201
|
onClickCapture={blockChildClickHandler}
|
|
202
|
+
className={classNames('slider__wrapper', {
|
|
203
|
+
'is-scrollable': isScrollable,
|
|
204
|
+
'is-dragging': isDragging,
|
|
205
|
+
})}
|
|
226
206
|
>
|
|
227
207
|
{Children.map(children, (child, index: number) => (
|
|
228
208
|
<div className="slider__wrapper__slide" role="listitem" key={index} data-slide-index={index} ref={(node) => { if (node) { addSlide(node, index); } }}>
|
|
@@ -230,32 +210,12 @@ export const Slider: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
230
210
|
</div>
|
|
231
211
|
))}
|
|
232
212
|
</div>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
>
|
|
240
|
-
<svg fill="#33333" viewBox="0 0 256 256" width="24" height="24" xmlns="http://www.w3.org/2000/svg">
|
|
241
|
-
<g>
|
|
242
|
-
<path d="M160,220a11.96287,11.96287,0,0,1-8.48535-3.51465l-80-80a12.00062,12.00062,0,0,1,0-16.9707l80-80a12.0001,12.0001,0,0,1,16.9707,16.9707L96.9707,128l71.51465,71.51465A12,12,0,0,1,160,220Z"></path>
|
|
243
|
-
</g>
|
|
244
|
-
</svg>
|
|
245
|
-
</button>
|
|
246
|
-
<button
|
|
247
|
-
aria-label="Next slide"
|
|
248
|
-
type="button"
|
|
249
|
-
onClick={() => navigate(NavigationDirection.NEXT)}
|
|
250
|
-
ref={arrowNextRef}
|
|
251
|
-
className="slider__button slider__button--next slider__button--hidden"
|
|
252
|
-
>
|
|
253
|
-
<svg fill="#333333" viewBox="0 0 256 256" width="24" height="24" xmlns="http://www.w3.org/2000/svg">
|
|
254
|
-
<g>
|
|
255
|
-
<path d="M96,220a12,12,0,0,1-8.48535-20.48535L159.0293,128,87.51465,56.48535a12.0001,12.0001,0,0,1,16.9707-16.9707l80,80a12.00062,12.00062,0,0,1,0,16.9707l-80,80A11.96287,11.96287,0,0,1,96,220Z"></path>
|
|
256
|
-
</g>
|
|
257
|
-
</svg>
|
|
258
|
-
</button>
|
|
213
|
+
{ hideNavigationButtons === false && (
|
|
214
|
+
<>
|
|
215
|
+
<PreviousButton onClick={() => navigate(NavigationDirection.PREV)} isHidden={prevArrowVisible === false}/>
|
|
216
|
+
<NextButton onClick={() => navigate(NavigationDirection.NEXT)} isHidden={nextArrowVisible === false}/>
|
|
217
|
+
</>
|
|
218
|
+
)}
|
|
259
219
|
</div>
|
|
260
220
|
);
|
|
261
221
|
};
|