Skip to content

Commit c9fa029

Browse files
authored
Merge pull request #106 from sag1v/next
Merge next to master
2 parents d8beca6 + 3bd5d57 commit c9fa029

File tree

2 files changed

+52
-24
lines changed

2 files changed

+52
-24
lines changed

src/react-elastic-carousel/components/Carousel.js

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react";
1+
import React, { Children } from "react";
22
import PropTypes from "prop-types";
33
import ResizeObserver from "resize-observer-polyfill";
44
import Only from "react-only-when";
@@ -49,10 +49,11 @@ class Carousel extends React.Component {
4949
} = this.props;
5050
const { activeIndex, sliderContainerWidth } = this.state;
5151
const nextItem = this.getNextItemIndex(activeIndex, false);
52-
52+
const currentChildrenLength = Children.toArray(children).length;
53+
const prevChildrenLength = Children.toArray(prevProps.children).length;
5354
// update pages (for pagination)
5455
if (
55-
prevProps.children !== children ||
56+
prevChildrenLength !== currentChildrenLength ||
5657
prevProps.itemsToShow !== itemsToShow ||
5758
prevProps.itemsToScroll !== itemsToScroll ||
5859
prevProps.breakPoints !== breakPoints ||
@@ -70,18 +71,18 @@ class Carousel extends React.Component {
7071
this.removeAutoPlay();
7172
}
7273

73-
if (prevProps.children.length > children.length) {
74+
if (prevChildrenLength !== currentChildrenLength) {
7475
const {
7576
itemsToShow: calculatedItemsToShow
7677
} = this.getDerivedPropsFromBreakPoint();
7778
// number of items is reduced (we don't care if number of items is increased)
7879
// we need to check if our current index is not out of boundaries
7980
// we need to include itemsToShow so we can fill up the slots
80-
const lastIndex = children.length - 1;
81+
const lastIndex = currentChildrenLength - 1;
8182
const isOutOfRange = activeIndex + calculatedItemsToShow > lastIndex;
8283
if (isOutOfRange) {
8384
// we are out of boundaries, go "back" to last item of the list (respect itemsToShow)
84-
this.goTo(Math.max(0, children.length - calculatedItemsToShow));
85+
this.goTo(Math.max(0, currentChildrenLength - calculatedItemsToShow));
8586
}
8687
}
8788
}
@@ -173,7 +174,7 @@ class Carousel extends React.Component {
173174
transitionMs
174175
} = this.getDerivedPropsFromBreakPoint();
175176
const { childWidth, childHeight, activeIndex } = state;
176-
const totalItems = children.length;
177+
const totalItems = Children.toArray(children).length;
177178
const hiddenSlots = totalItems - itemsToShow;
178179
let moveBy = activeIndex * -1;
179180
const emptySlots = itemsToShow - (totalItems - activeIndex);
@@ -200,34 +201,51 @@ class Carousel extends React.Component {
200201
children,
201202
itemsToShow
202203
} = this.getDerivedPropsFromBreakPoint();
203-
const { height } = sliderNode.contentRect;
204+
const { height: sliderHeight } = sliderNode.contentRect;
204205
const nextState = {};
206+
const childrenLength = Children.toArray(children).length;
205207
if (verticalMode) {
206-
const childHeight = height / children.length;
207-
nextState.rootHeight = childHeight * itemsToShow;
208+
const childHeight = sliderHeight / childrenLength;
209+
// We use Math.min because don't want to make the child smaller
210+
// if number of children is smaller than itemsToShow.
211+
// Because we will have "empty slots"
212+
nextState.rootHeight =
213+
childHeight * Math.min(childrenLength, itemsToShow);
208214
nextState.childHeight = childHeight;
209215
} else {
210-
nextState.rootHeight = height;
216+
nextState.rootHeight = sliderHeight;
211217
}
212218
this.setState(nextState);
213219
};
214220

215221
onContainerResize = sliderContainerNode => {
216-
const { width } = sliderContainerNode.contentRect;
222+
const { width: sliderContainerWidth } = sliderContainerNode.contentRect;
217223
// update slider container width
218224
// disable animation on resize see https://github.com/sag1v/react-elastic-carousel/issues/94
219-
this.setState({ sliderContainerWidth: width, transitionMs: 0 }, () => {
225+
this.setState({ sliderContainerWidth, transitionMs: 0 }, () => {
220226
// we must get these props inside setState (get future props because its async)
221227
const {
222228
onResize,
223229
verticalMode,
224-
itemsToShow
230+
itemsToShow,
231+
children
225232
} = this.getDerivedPropsFromBreakPoint();
226233

227234
/* based on slider container's width, get num of items to show
228235
* and calculate child's width (and update it in state)
229236
*/
230-
const childWidth = verticalMode ? width : width / itemsToShow;
237+
const childrenLength = Children.toArray(children).length;
238+
let childWidth = 0;
239+
if (verticalMode) {
240+
childWidth = sliderContainerWidth;
241+
} else {
242+
// We use Math.min because don't want to make the child smaller
243+
// if number of children is smaller than itemsToShow.
244+
// Because we will have "empty slots"
245+
childWidth =
246+
sliderContainerWidth / Math.min(childrenLength, itemsToShow);
247+
}
248+
231249
this.setState(
232250
state => ({ childWidth }),
233251
() => {
@@ -263,7 +281,7 @@ class Carousel extends React.Component {
263281
const { children } = this.props;
264282
// support decimal itemsToShow
265283
const roundedIdx = Math.round(index);
266-
const child = children[roundedIdx];
284+
const child = Children.toArray(children)[roundedIdx];
267285
return { item: child.props, index: roundedIdx };
268286
};
269287

@@ -273,8 +291,9 @@ class Carousel extends React.Component {
273291
itemsToShow,
274292
itemsToScroll
275293
} = this.getDerivedPropsFromBreakPoint();
276-
const notEnoughItemsToShow = itemsToShow > children.length;
277-
let limit = getPrev ? 0 : children.length - itemsToShow;
294+
const childrenLength = Children.toArray(children).length;
295+
const notEnoughItemsToShow = itemsToShow > childrenLength;
296+
let limit = getPrev ? 0 : childrenLength - itemsToShow;
278297

279298
if (notEnoughItemsToShow) {
280299
limit = 0; // basically don't move
@@ -292,7 +311,7 @@ class Carousel extends React.Component {
292311
const nextItemIndex = this.getNextItemIndex(activeIndex, getPrev);
293312
// support decimal itemsToShow
294313
const roundedIdx = Math.round(nextItemIndex);
295-
const asElement = children[roundedIdx];
314+
const asElement = Children.toArray(children)[roundedIdx];
296315
const asObj = { item: asElement.props, index: roundedIdx };
297316
return asObj;
298317
};
@@ -323,8 +342,9 @@ class Carousel extends React.Component {
323342
} = this.getDerivedPropsFromBreakPoint();
324343

325344
// determine how far can user swipe
345+
const childrenLength = Children.toArray(children).length;
326346
const isOnStart = activeIndex === 0;
327-
const isOnEnd = activeIndex === children.length - itemsToShow;
347+
const isOnEnd = activeIndex === childrenLength - itemsToShow;
328348
const defaultDivider = 1.5;
329349
const largeDivider = itemsToShow * 2;
330350
let divider = defaultDivider;
@@ -535,16 +555,17 @@ class Carousel extends React.Component {
535555
itemsToShow
536556
} = this.getDerivedPropsFromBreakPoint();
537557
const { activeIndex } = this.state;
558+
const childrenLength = Children.toArray(children).length;
538559
const isPrev = activeIndex > nextItemId;
539560
const nextAvailbaleItem = this.getNextItemIndex(activeIndex, isPrev);
540561
const noChange = nextAvailbaleItem === activeIndex;
541-
const outOfBoundry = nextItemId + itemsToShow >= children.length;
562+
const outOfBoundry = nextItemId + itemsToShow >= childrenLength;
542563
if (noChange) {
543564
return;
544565
}
545566
if (outOfBoundry) {
546567
// Either go to last index (respect itemsToShow) or 0 index if we can't fill the slider
547-
nextItemId = Math.max(0, children.length - itemsToShow);
568+
nextItemId = Math.max(0, childrenLength - itemsToShow);
548569
}
549570
let direction = consts.NEXT;
550571
let positionEndCb = this.onNextEnd;
@@ -571,7 +592,8 @@ class Carousel extends React.Component {
571592

572593
getNumOfPages = () => {
573594
const { children, itemsToShow } = this.getDerivedPropsFromBreakPoint();
574-
const numOfPages = Math.ceil(children.length / itemsToShow);
595+
const childrenLength = Children.toArray(children).length;
596+
const numOfPages = Math.ceil(childrenLength / itemsToShow);
575597
return numOfPages || 1;
576598
};
577599

@@ -681,7 +703,7 @@ class Carousel extends React.Component {
681703
>
682704
<Track
683705
verticalMode={verticalMode}
684-
children={children}
706+
children={Children.toArray(children)}
685707
childWidth={childWidth}
686708
currentItem={activeIndex}
687709
autoTabIndexVisibleItems={autoTabIndexVisibleItems}

src/react-elastic-carousel/components/__tests__/Carousel.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ describe("Carousel - public API (props)", () => {
2222
expect(children.length).toEqual(Items.length);
2323
});
2424

25+
it("one child wont break on next", () => {
26+
const wrapper = mount(<Carousel>{Items[0]}</Carousel>);
27+
const nextButton = wrapper.find(Carousel).find("button.rec-arrow-right");
28+
nextButton.simulate("click");
29+
});
30+
2531
it("renders with className in root", () => {
2632
const testClassName = "test-root";
2733
const wrapper = mount(

0 commit comments

Comments
 (0)