Skip to content

Commit a9d8c39

Browse files
mariohoyos92tim-steele
authored andcommitted
feature: infinite scroll works with swiping as well as buttons (#204)
1 parent 9a84414 commit a9d8c39

File tree

5 files changed

+54
-4
lines changed

5 files changed

+54
-4
lines changed

src/App/examples/Example12/Example12.jsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ export default () => (
1818
>
1919
<h2 className={s.headline}>Infinite Carousel</h2>
2020
<p>
21-
A carousel that returns to the first slide if the user clicks the Next button while on the
22-
last slide and returns to the last slide if the user clicks the Back
23-
button while on the first slide.
21+
A carousel that returns to the first slide if the user clicks the Next
22+
button while on the last slide and returns to the last slide if the user
23+
clicks the Back button while on the first slide. Also behaves similarly
24+
with swiping left on the first image or right on the last image.
2425
</p>
2526
<Slider className={s.slider}>
2627
<Slide index={0}>

src/Slider/Slider.jsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const Slider = class Slider extends React.Component {
2121
dragEnabled: PropTypes.bool.isRequired,
2222
dragStep: PropTypes.number,
2323
hasMasterSpinner: PropTypes.bool.isRequired,
24+
infinite: PropTypes.bool,
2425
interval: PropTypes.number.isRequired,
2526
isPageScrollLocked: PropTypes.bool.isRequired,
2627
isPlaying: PropTypes.bool.isRequired,
@@ -64,6 +65,7 @@ const Slider = class Slider extends React.Component {
6465
disableAnimation: false,
6566
disableKeyboard: false,
6667
dragStep: 1,
68+
infinite: false,
6769
moveThreshold: 0.1,
6870
onMasterSpinner: null,
6971
privateUnDisableAnimation: false,
@@ -456,12 +458,21 @@ const Slider = class Slider extends React.Component {
456458
this.props.totalSlides, this.props.visibleSlides,
457459
);
458460

459-
const currentSlide = boundedRange({
461+
let currentSlide = boundedRange({
460462
min: 0,
461463
max: maxSlide,
462464
x: (this.props.currentSlide + slidesMoved),
463465
});
464466

467+
if (this.props.infinite) {
468+
if (this.props.currentSlide >= maxSlide && slidesMoved > 0) {
469+
currentSlide = 0;
470+
}
471+
if (this.props.currentSlide === 0 && slidesMoved < 0) {
472+
currentSlide = maxSlide;
473+
}
474+
}
475+
465476
this.props.carouselStore.setStoreState({
466477
currentSlide,
467478
});

src/Slider/__tests__/Slider.test.jsx

+36
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,42 @@ describe('<Slider />', () => {
628628
expect(props.carouselStore.state.currentSlide).toBe(3);
629629
});
630630

631+
it('Should set the slider to last set of visible slides on touchend when dragging the slider past the start of the slide show and infinite is set to true.', () => {
632+
const wrapper = mount(<Slider {...props} infinite currentSlide={0} />);
633+
const instance = wrapper.instance();
634+
wrapper.setState({
635+
deltaX: 1000,
636+
deltaY: 0,
637+
});
638+
wrapper.update();
639+
instance.sliderTrayElement = {
640+
clientWidth: 500,
641+
clientHeight: 100,
642+
};
643+
wrapper.find('.sliderTray').simulate('touchend', { targetTouches: [] });
644+
expect(props.carouselStore.state.currentSlide).toBe(
645+
props.totalSlides - props.visibleSlides,
646+
);
647+
});
648+
649+
it('Should set the slider to first set of visible slides on touchend when dragging the slider past the end of the last slide and infinite is set to true.', () => {
650+
const wrapper = mount(
651+
<Slider {...props} infinite currentSlide={props.totalSlides - 1} />,
652+
);
653+
const instance = wrapper.instance();
654+
wrapper.setState({
655+
deltaX: -1000,
656+
deltaY: 0,
657+
});
658+
wrapper.update();
659+
instance.sliderTrayElement = {
660+
clientWidth: 500,
661+
clientHeight: 100,
662+
};
663+
wrapper.find('.sliderTray').simulate('touchend', { targetTouches: [] });
664+
expect(props.carouselStore.state.currentSlide).toBe(0);
665+
});
666+
631667
it('should not change the state at all when touchEnd and touchEnabled prop is false', () => {
632668
const wrapper = shallow(<Slider {...props} touchEnabled={false} />);
633669
// nonsense values to test that slider state is not reset on touchend

src/Slider/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default WithStore(Slider, state => ({
88
disableKeyboard: state.disableKeyboard,
99
dragEnabled: state.dragEnabled,
1010
hasMasterSpinner: state.hasMasterSpinner,
11+
infinite: state.infinite,
1112
interval: state.interval,
1213
isPageScrollLocked: state.isPageScrollLocked,
1314
isPlaying: state.isPlaying,

src/helpers/component-config.js

+1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export default {
153153
dragEnabled: true,
154154
hasMasterSpinner: false,
155155
interval: 5000,
156+
infinite: false,
156157
isPageScrollLocked: false,
157158
isPlaying: false,
158159
lockOnWindowScroll: false,

0 commit comments

Comments
 (0)