From 0a15fe7f247606536daab7751cb84b715c63b144 Mon Sep 17 00:00:00 2001 From: Bryan Mey Date: Fri, 23 Mar 2018 15:09:12 -0400 Subject: [PATCH] fic(Carousel): fix animation direction when using `CarouselIndicators` (#749) Closes #748 --- src/Carousel.js | 18 ++++++-- src/__tests__/Carousel.spec.js | 78 +++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/Carousel.js b/src/Carousel.js index e6c4360e2..090e375fe 100644 --- a/src/Carousel.js +++ b/src/Carousel.js @@ -11,7 +11,10 @@ class Carousel extends React.Component { this.renderItems = this.renderItems.bind(this); this.hoverStart = this.hoverStart.bind(this); this.hoverEnd = this.hoverEnd.bind(this); - this.state = { direction: 'right' }; + this.state = { + direction: 'right', + indicatorClicked: false, + }; } getChildContext() { @@ -36,10 +39,11 @@ class Carousel extends React.Component { } else if (this.props.activeIndex - 1 === nextProps.activeIndex) { this.setState({ direction: 'left' }); } else if (this.props.activeIndex > nextProps.activeIndex) { - this.setState({ direction: 'right' }); + this.setState({ direction: this.state.indicatorClicked ? 'left' : 'right' }); } else if (this.props.activeIndex !== nextProps.activeIndex) { - this.setState({ direction: 'left' }); + this.setState({ direction: this.state.indicatorClicked ? 'right' : 'left' }); } + this.setState({ indicatorClicked: false }); } componentWillUnmount() { @@ -145,13 +149,19 @@ class Carousel extends React.Component { // Rendering indicators, slides and controls const indicators = children[0]; + const wrappedOnClick = (e) => { + if (typeof indicators.props.onClickHandler === 'function') { + this.setState({ indicatorClicked: true }, () => indicators.props.onClickHandler(e)); + } + }; + const wrappedIndicators = React.cloneElement(indicators, { onClickHandler: wrappedOnClick }); const carouselItems = children[1]; const controlLeft = children[2]; const controlRight = children[3]; return (
- {indicators} + {wrappedIndicators} {this.renderItems(carouselItems, innerClasses)} {controlLeft} {controlRight} diff --git a/src/__tests__/Carousel.spec.js b/src/__tests__/Carousel.spec.js index 1b4fc1f56..b7c74f0c2 100644 --- a/src/__tests__/Carousel.spec.js +++ b/src/__tests__/Carousel.spec.js @@ -234,6 +234,30 @@ describe('Carousel', () => { }); describe('carouseling', () => { + it('should set indicatorClicked to true if indicator clicked', () => { + const slides = items.map((item, idx) => { + return ( + + + + ); + }); + + const wrapper = mount( + { }} previous={() => { }}> + function () {}} /> + {slides} + { }} /> + { }} /> + + ); + + wrapper.find(CarouselIndicators).find('li').first().simulate('click'); + expect(wrapper.state().indicatorClicked).toEqual(true); + }); + it('should go right when the index increases', () => { const slides = items.map((item, idx) => { return ( @@ -276,7 +300,7 @@ describe('Carousel', () => { expect(wrapper.state().direction).toEqual('left'); }); - it('should go right if transitioning from the last to first slide', () => { + it('should go right if transitioning from the last to first slide by non-indicator', () => { const slides = items.map((item, idx) => { return ( { expect(wrapper.state().direction).toEqual('right'); }); - it('should go left if transitioning from the first to last slide', () => { + it('should go left if transitioning from the last to first slide by indicator', () => { + const slides = items.map((item, idx) => { + return ( + + + + ); + }); + + const wrapper = mount( + { }} previous={() => { }}> + { }} /> + {slides} + { }} /> + { }} /> + + ); + + wrapper.setState({ indicatorClicked: true }); + wrapper.setProps({ activeIndex: 0 }); + expect(wrapper.state().direction).toEqual('left'); + }); + + it('should go left if transitioning from the first to last slide by non-indicator', () => { const slides = items.map((item, idx) => { return ( { }); }); + it('should go right if transitioning from the first to last slide by indicator', () => { + const slides = items.map((item, idx) => { + return ( + + + + ); + }); + + const wrapper = mount( + { }} previous={() => { }}> + { }} /> + {slides} + { }} /> + { }} /> + + ); + + wrapper.setState({ indicatorClicked: true }); + wrapper.setProps({ activeIndex: 2 }); + expect(wrapper.state().direction).toEqual('right'); + }); + describe('interval', () => { it('should not autoplay by default', () => { const next = jest.fn();