@lumx/react 3.9.3 → 3.9.4-alpha.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/index.d.ts +11 -9
- package/index.js +426 -415
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/image-lightbox/internal/ImageSlideshow.tsx +2 -0
- package/src/components/slideshow/Slides.tsx +7 -5
- package/src/components/slideshow/Slideshow.stories.tsx +12 -1
- package/src/components/slideshow/Slideshow.tsx +2 -16
- package/src/components/slideshow/SlideshowControls.stories.tsx +2 -3
- package/src/components/slideshow/SlideshowControls.tsx +63 -73
- package/src/components/slideshow/SlideshowItem.tsx +1 -10
- package/src/components/slideshow/SlideshowItemGroup.tsx +16 -33
- package/src/components/slideshow/useSlideFocusManagement.tsx +51 -36
- package/src/{hooks → components/slideshow}/useSlideshowControls.ts +57 -60
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { SetStateAction, useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { clamp } from '@lumx/react';
|
|
3
3
|
import { useInterval } from '@lumx/react/hooks/useInterval';
|
|
4
|
-
import { AUTOPLAY_DEFAULT_INTERVAL } from '@lumx/react/components/slideshow/constants';
|
|
5
4
|
import { useId } from '@lumx/react/hooks/useId';
|
|
6
5
|
|
|
6
|
+
import { AUTOPLAY_DEFAULT_INTERVAL } from './constants';
|
|
7
|
+
|
|
7
8
|
export interface UseSlideshowControlsOptions {
|
|
8
9
|
/** default active index to be displayed */
|
|
9
10
|
defaultActiveIndex?: number;
|
|
@@ -43,9 +44,9 @@ export interface UseSlideshowControls {
|
|
|
43
44
|
/** id to be used for the wrapper that contains the slides */
|
|
44
45
|
slideshowSlidesId: string;
|
|
45
46
|
/** callback that triggers the previous slide while using the slideshow controls */
|
|
46
|
-
onPreviousClick: (
|
|
47
|
+
onPreviousClick: (loopBack: boolean) => void;
|
|
47
48
|
/** callback that triggers the next slide while using the slideshow controls */
|
|
48
|
-
onNextClick: (
|
|
49
|
+
onNextClick: (loopBack: boolean) => void;
|
|
49
50
|
/** callback that triggers a specific page while using the slideshow controls */
|
|
50
51
|
onPaginationClick: (index: number) => void;
|
|
51
52
|
/** whether the slideshow is autoplaying or not */
|
|
@@ -54,16 +55,18 @@ export interface UseSlideshowControls {
|
|
|
54
55
|
isForcePaused: boolean;
|
|
55
56
|
/** callback to change whether the slideshow is autoplaying or not */
|
|
56
57
|
toggleAutoPlay: () => void;
|
|
57
|
-
/**
|
|
58
|
+
/** callback to change whether the slideshow should be force paused or not */
|
|
58
59
|
toggleForcePause: () => void;
|
|
59
60
|
/** current active slide index */
|
|
60
61
|
activeIndex: number;
|
|
61
62
|
/** set the current index as the active one */
|
|
62
63
|
setActiveIndex: (index: number) => void;
|
|
63
|
-
/** callback that stops the
|
|
64
|
+
/** callback that stops the autoplay */
|
|
64
65
|
stopAutoPlay: () => void;
|
|
65
|
-
/** callback that starts the
|
|
66
|
+
/** callback that starts the autoplay */
|
|
66
67
|
startAutoPlay: () => void;
|
|
68
|
+
/** True if the last slide change is user activated */
|
|
69
|
+
isUserActivated?: boolean;
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
export const DEFAULT_OPTIONS: Partial<UseSlideshowControlsOptions> = {
|
|
@@ -90,40 +93,34 @@ export const useSlideshowControls = ({
|
|
|
90
93
|
// Number of slides when using groupBy prop.
|
|
91
94
|
const slidesCount = Math.ceil(itemsCount / Math.min(groupBy as number, itemsCount));
|
|
92
95
|
|
|
93
|
-
//
|
|
94
|
-
const
|
|
95
|
-
(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
return index;
|
|
106
|
-
});
|
|
96
|
+
// Set current active index (& if is user activated)
|
|
97
|
+
const setActiveIndex = useCallback(
|
|
98
|
+
(setStateAction: SetStateAction<number>, isUser?: boolean) => {
|
|
99
|
+
// Store on element a boolean value when the slide change was not from a user action.
|
|
100
|
+
const elementDataset = element?.dataset as any;
|
|
101
|
+
if (elementDataset) {
|
|
102
|
+
if (isUser) elementDataset.lumxUserActivated = true;
|
|
103
|
+
else delete elementDataset.lumxUserActivated;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setCurrentIndex(setStateAction);
|
|
107
107
|
},
|
|
108
|
-
[
|
|
108
|
+
[element],
|
|
109
109
|
);
|
|
110
110
|
|
|
111
|
-
// Change
|
|
112
|
-
const
|
|
113
|
-
(
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
return slidesCount
|
|
111
|
+
// Change slide given delta (-1/+1) with or without loop back.
|
|
112
|
+
const goTo = useCallback(
|
|
113
|
+
(delta: -1 | 1 = 1, loopBack = true, isUser?: boolean) => {
|
|
114
|
+
setActiveIndex((index) => {
|
|
115
|
+
if (loopBack) {
|
|
116
|
+
const newIndex = (index + delta) % slidesCount;
|
|
117
|
+
if (newIndex < 0) return slidesCount + newIndex;
|
|
118
|
+
return newIndex;
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return index - 1;
|
|
122
|
-
}
|
|
123
|
-
return index;
|
|
124
|
-
});
|
|
120
|
+
return clamp(index + delta, 0, slidesCount - 1);
|
|
121
|
+
}, isUser);
|
|
125
122
|
},
|
|
126
|
-
[slidesCount,
|
|
123
|
+
[slidesCount, setActiveIndex],
|
|
127
124
|
);
|
|
128
125
|
|
|
129
126
|
// Auto play
|
|
@@ -132,22 +129,22 @@ export const useSlideshowControls = ({
|
|
|
132
129
|
|
|
133
130
|
const isSlideshowAutoPlaying = isForcePaused ? false : isAutoPlaying;
|
|
134
131
|
// Start
|
|
135
|
-
useInterval(
|
|
132
|
+
useInterval(goTo, isSlideshowAutoPlaying && slidesCount > 1 ? (interval as number) : null);
|
|
136
133
|
|
|
137
|
-
// Reset current index if it
|
|
134
|
+
// Reset current index if it becomes invalid.
|
|
138
135
|
useEffect(() => {
|
|
139
136
|
if (currentIndex > slidesCount - 1) {
|
|
140
|
-
|
|
137
|
+
setActiveIndex(defaultActiveIndex as number);
|
|
141
138
|
}
|
|
142
|
-
}, [currentIndex, slidesCount, defaultActiveIndex]);
|
|
139
|
+
}, [currentIndex, slidesCount, defaultActiveIndex, setActiveIndex]);
|
|
143
140
|
|
|
144
|
-
const startAutoPlay = () => {
|
|
141
|
+
const startAutoPlay = useCallback(() => {
|
|
145
142
|
setIsAutoPlaying(Boolean(autoPlay));
|
|
146
|
-
};
|
|
143
|
+
}, [autoPlay]);
|
|
147
144
|
|
|
148
|
-
const stopAutoPlay = () => {
|
|
145
|
+
const stopAutoPlay = useCallback(() => {
|
|
149
146
|
setIsAutoPlaying(false);
|
|
150
|
-
};
|
|
147
|
+
}, []);
|
|
151
148
|
|
|
152
149
|
// Handle click on a bullet to go to a specific slide.
|
|
153
150
|
const onPaginationClick = useCallback(
|
|
@@ -156,36 +153,36 @@ export const useSlideshowControls = ({
|
|
|
156
153
|
setIsForcePaused(true);
|
|
157
154
|
|
|
158
155
|
if (index >= 0 && index < slidesCount) {
|
|
159
|
-
|
|
156
|
+
setActiveIndex(index, true);
|
|
160
157
|
}
|
|
161
158
|
},
|
|
162
|
-
[slidesCount,
|
|
159
|
+
[stopAutoPlay, slidesCount, setActiveIndex],
|
|
163
160
|
);
|
|
164
161
|
|
|
165
162
|
// Handle click or keyboard event to go to next slide.
|
|
166
163
|
const onNextClick = useCallback(
|
|
167
|
-
(
|
|
164
|
+
(loopBack = true) => {
|
|
168
165
|
stopAutoPlay();
|
|
169
166
|
setIsForcePaused(true);
|
|
170
|
-
|
|
167
|
+
goTo(1, loopBack, true);
|
|
171
168
|
},
|
|
172
|
-
[
|
|
169
|
+
[goTo, stopAutoPlay],
|
|
173
170
|
);
|
|
174
171
|
|
|
175
172
|
// Handle click or keyboard event to go to previous slide.
|
|
176
173
|
const onPreviousClick = useCallback(
|
|
177
|
-
(
|
|
174
|
+
(loopBack = true) => {
|
|
178
175
|
stopAutoPlay();
|
|
179
176
|
setIsForcePaused(true);
|
|
180
|
-
|
|
177
|
+
goTo(-1, loopBack, true);
|
|
181
178
|
},
|
|
182
|
-
[
|
|
179
|
+
[goTo, stopAutoPlay],
|
|
183
180
|
);
|
|
184
181
|
|
|
185
182
|
// If the activeIndex props changes, update the current slide
|
|
186
183
|
useEffect(() => {
|
|
187
|
-
|
|
188
|
-
}, [activeIndex]);
|
|
184
|
+
setActiveIndex(activeIndex as number);
|
|
185
|
+
}, [activeIndex, setActiveIndex]);
|
|
189
186
|
|
|
190
187
|
// If the slide changes, with autoplay for example, trigger "onChange"
|
|
191
188
|
useEffect(() => {
|
|
@@ -199,15 +196,15 @@ export const useSlideshowControls = ({
|
|
|
199
196
|
const generatedSlidesId = useId();
|
|
200
197
|
const slideshowSlidesId = slidesId || generatedSlidesId;
|
|
201
198
|
|
|
202
|
-
const toggleAutoPlay = () => {
|
|
199
|
+
const toggleAutoPlay = useCallback(() => {
|
|
203
200
|
if (isSlideshowAutoPlaying) {
|
|
204
201
|
stopAutoPlay();
|
|
205
202
|
} else {
|
|
206
203
|
startAutoPlay();
|
|
207
204
|
}
|
|
208
|
-
};
|
|
205
|
+
}, [isSlideshowAutoPlaying, startAutoPlay, stopAutoPlay]);
|
|
209
206
|
|
|
210
|
-
const toggleForcePause = () => {
|
|
207
|
+
const toggleForcePause = useCallback(() => {
|
|
211
208
|
const shouldBePaused = !isForcePaused;
|
|
212
209
|
|
|
213
210
|
setIsForcePaused(shouldBePaused);
|
|
@@ -217,7 +214,7 @@ export const useSlideshowControls = ({
|
|
|
217
214
|
} else {
|
|
218
215
|
stopAutoPlay();
|
|
219
216
|
}
|
|
220
|
-
};
|
|
217
|
+
}, [isForcePaused, startAutoPlay, stopAutoPlay]);
|
|
221
218
|
|
|
222
219
|
// Start index and end index of visible slides.
|
|
223
220
|
const startIndexVisible = currentIndex * (groupBy as number);
|
|
@@ -237,7 +234,7 @@ export const useSlideshowControls = ({
|
|
|
237
234
|
toggleAutoPlay,
|
|
238
235
|
activeIndex: currentIndex,
|
|
239
236
|
slidesCount,
|
|
240
|
-
setActiveIndex
|
|
237
|
+
setActiveIndex,
|
|
241
238
|
startAutoPlay,
|
|
242
239
|
stopAutoPlay,
|
|
243
240
|
isForcePaused,
|