Skip to content

feature: infinite scroll works with swiping as well as buttons #204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/App/examples/Example12/Example12.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ export default () => (
>
<h2 className={s.headline}>Infinite Carousel</h2>
<p>
A carousel that returns to the first slide if the user clicks the Next button while on the
last slide and returns to the last slide if the user clicks the Back
button while on the first slide.
A carousel that returns to the first slide if the user clicks the Next
button while on the last slide and returns to the last slide if the user
clicks the Back button while on the first slide. Also behaves similarly
with swiping left on the first image or right on the last image.
</p>
<Slider className={s.slider}>
<Slide index={0}>
Expand Down
13 changes: 12 additions & 1 deletion src/Slider/Slider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const Slider = class Slider extends React.Component {
dragEnabled: PropTypes.bool.isRequired,
dragStep: PropTypes.number,
hasMasterSpinner: PropTypes.bool.isRequired,
infinite: PropTypes.bool,
interval: PropTypes.number.isRequired,
isPageScrollLocked: PropTypes.bool.isRequired,
isPlaying: PropTypes.bool.isRequired,
Expand Down Expand Up @@ -64,6 +65,7 @@ const Slider = class Slider extends React.Component {
disableAnimation: false,
disableKeyboard: false,
dragStep: 1,
infinite: false,
moveThreshold: 0.1,
onMasterSpinner: null,
privateUnDisableAnimation: false,
Expand Down Expand Up @@ -456,12 +458,21 @@ const Slider = class Slider extends React.Component {
this.props.totalSlides, this.props.visibleSlides,
);

const currentSlide = boundedRange({
let currentSlide = boundedRange({
min: 0,
max: maxSlide,
x: (this.props.currentSlide + slidesMoved),
});

if (this.props.infinite) {
if (this.props.currentSlide >= maxSlide && slidesMoved > 0) {
currentSlide = 0;
}
if (this.props.currentSlide === 0 && slidesMoved < 0) {
currentSlide = maxSlide;
}
}

this.props.carouselStore.setStoreState({
currentSlide,
});
Expand Down
36 changes: 36 additions & 0 deletions src/Slider/__tests__/Slider.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,42 @@ describe('<Slider />', () => {
expect(props.carouselStore.state.currentSlide).toBe(3);
});

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.', () => {
const wrapper = mount(<Slider {...props} infinite currentSlide={0} />);
const instance = wrapper.instance();
wrapper.setState({
deltaX: 1000,
deltaY: 0,
});
wrapper.update();
instance.sliderTrayElement = {
clientWidth: 500,
clientHeight: 100,
};
wrapper.find('.sliderTray').simulate('touchend', { targetTouches: [] });
expect(props.carouselStore.state.currentSlide).toBe(
props.totalSlides - props.visibleSlides,
);
});

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.', () => {
const wrapper = mount(
<Slider {...props} infinite currentSlide={props.totalSlides - 1} />,
);
const instance = wrapper.instance();
wrapper.setState({
deltaX: -1000,
deltaY: 0,
});
wrapper.update();
instance.sliderTrayElement = {
clientWidth: 500,
clientHeight: 100,
};
wrapper.find('.sliderTray').simulate('touchend', { targetTouches: [] });
expect(props.carouselStore.state.currentSlide).toBe(0);
});

it('should not change the state at all when touchEnd and touchEnabled prop is false', () => {
const wrapper = shallow(<Slider {...props} touchEnabled={false} />);
// nonsense values to test that slider state is not reset on touchend
Expand Down
1 change: 1 addition & 0 deletions src/Slider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default WithStore(Slider, state => ({
disableKeyboard: state.disableKeyboard,
dragEnabled: state.dragEnabled,
hasMasterSpinner: state.hasMasterSpinner,
infinite: state.infinite,
interval: state.interval,
isPageScrollLocked: state.isPageScrollLocked,
isPlaying: state.isPlaying,
Expand Down
1 change: 1 addition & 0 deletions src/helpers/component-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export default {
dragEnabled: true,
hasMasterSpinner: false,
interval: 5000,
infinite: false,
isPageScrollLocked: false,
isPlaying: false,
lockOnWindowScroll: false,
Expand Down