From b986a7923e9f1d32433f1955b745cd15b4d72e20 Mon Sep 17 00:00:00 2001 From: "sagiv.bengiat" Date: Fri, 13 Nov 2020 10:22:31 +0200 Subject: [PATCH 1/4] fix infinite refresh with gatsby (ssr?) --- .../components/Carousel.js | 134 +++++++++--------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/src/react-elastic-carousel/components/Carousel.js b/src/react-elastic-carousel/components/Carousel.js index eba7550..629ac41 100644 --- a/src/react-elastic-carousel/components/Carousel.js +++ b/src/react-elastic-carousel/components/Carousel.js @@ -11,7 +11,7 @@ import { SliderContainer, Slider, StyledCarousel, - CarouselWrapper + CarouselWrapper, } from "./styled"; import { pipe, noop, cssPrefix, numberToArray } from "../utils/helpers"; import { Pagination } from "./Pagination"; @@ -30,7 +30,7 @@ class Carousel extends React.Component { activeIndex: this.props.initialActiveIndex || this.props.initialFirstItem, // support deprecated initialFirstItem pages: [], activePage: 0, - sliderContainerWidth: 0 + sliderContainerWidth: 0, }; componentDidMount() { @@ -45,7 +45,7 @@ class Carousel extends React.Component { children, itemsToShow, itemsToScroll, - breakPoints + breakPoints, } = this.props; const { activeIndex, sliderContainerWidth } = this.state; const nextItem = this.getNextItemIndex(activeIndex, false); @@ -73,7 +73,7 @@ class Carousel extends React.Component { if (prevChildrenLength !== currentChildrenLength) { const { - itemsToShow: calculatedItemsToShow + itemsToShow: calculatedItemsToShow, } = this.getDerivedPropsFromBreakPoint(); // number of items is reduced (we don't care if number of items is increased) // we need to check if our current index is not out of boundaries @@ -91,16 +91,26 @@ class Carousel extends React.Component { this.unSubscribeObserver(); } - setRef = name => ref => (this[name] = ref); + setRef = (name) => (ref) => (this[name] = ref); initResizeObserver = () => { this.ro = new ResizeObserver((entries, observer) => { for (const entry of entries) { if (entry.target === this.sliderContainer) { - this.onContainerResize(entry); + // we are using rAF because it fixes the infinite refresh with gatsby (ssr?). + // TBH, I'm not sure i fully understand why. + // see https://github.com/sag1v/react-elastic-carousel/issues/107 + requestAnimationFrame(() => { + this.onContainerResize(entry); + }); } if (entry.target === this.slider) { - this.onSliderResize(entry); + // we are using rAF because it fixes the infinite refresh with gatsby (ssr?). + // TBH, I'm not sure i fully understand why + // see https://github.com/sag1v/react-elastic-carousel/issues/107 + requestAnimationFrame(() => { + this.onSliderResize(entry); + }); } } }); @@ -134,11 +144,11 @@ class Carousel extends React.Component { this.setState({ pages }); }; - onSliderTransitionEnd = fn => { + onSliderTransitionEnd = (fn) => { this.slider.addEventListener("transitionend", fn); }; - removeSliderTransitionHook = fn => { + removeSliderTransitionHook = (fn) => { this.slider.removeEventListener("transitionend", fn); }; @@ -153,11 +163,11 @@ class Carousel extends React.Component { currentBreakPoint = breakPoints .slice() // no mutations .reverse() // so we can find last match - .find(bp => bp.width <= sliderContainerWidth); + .find((bp) => bp.width <= sliderContainerWidth); if (!currentBreakPoint) { /* in case we don't have a lower width than sliderContainerWidth - * this mostly happens in initilization when sliderContainerWidth is 0 - */ + * this mostly happens in initilization when sliderContainerWidth is 0 + */ currentBreakPoint = breakPoints[0]; } } @@ -166,12 +176,12 @@ class Carousel extends React.Component { }; updateSliderPosition = () => { - this.setState(state => { + this.setState((state) => { const { children, verticalMode, itemsToShow, - transitionMs + transitionMs, } = this.getDerivedPropsFromBreakPoint(); const { childWidth, childHeight, activeIndex } = state; const totalItems = Children.toArray(children).length; @@ -190,16 +200,16 @@ class Carousel extends React.Component { window.requestAnimationFrame(() => this.setState({ transitionMs })); return { sliderPosition, - activeIndex: newActiveIndex < 0 ? 0 : newActiveIndex + activeIndex: newActiveIndex < 0 ? 0 : newActiveIndex, }; }); }; - onSliderResize = sliderNode => { + onSliderResize = (sliderNode) => { const { verticalMode, children, - itemsToShow + itemsToShow, } = this.getDerivedPropsFromBreakPoint(); const { height: sliderHeight } = sliderNode.contentRect; const nextState = {}; @@ -218,7 +228,7 @@ class Carousel extends React.Component { this.setState(nextState); }; - onContainerResize = sliderContainerNode => { + onContainerResize = (sliderContainerNode) => { const { width: sliderContainerWidth } = sliderContainerNode.contentRect; // update slider container width // disable animation on resize see https://github.com/sag1v/react-elastic-carousel/issues/94 @@ -228,12 +238,12 @@ class Carousel extends React.Component { onResize, verticalMode, itemsToShow, - children + children, } = this.getDerivedPropsFromBreakPoint(); /* based on slider container's width, get num of items to show - * and calculate child's width (and update it in state) - */ + * and calculate child's width (and update it in state) + */ const childrenLength = Children.toArray(children).length; let childWidth = 0; if (verticalMode) { @@ -247,13 +257,13 @@ class Carousel extends React.Component { } this.setState( - state => ({ childWidth }), + (state) => ({ childWidth }), () => { /* Based on all of the above new data: - * update slider position - * get the new current breakpoint - * pass the current breakpoint to the consumer's callback - */ + * update slider position + * get the new current breakpoint + * pass the current breakpoint to the consumer's callback + */ this.updateSliderPosition(); const currentBreakPoint = this.getDerivedPropsFromBreakPoint(); onResize(currentBreakPoint); @@ -263,21 +273,21 @@ class Carousel extends React.Component { }; tiltMovement = (position, distance = 20, duration = 150) => { - this.setState(state => { + this.setState((state) => { return { isSwiping: true, - swipedSliderPosition: position - distance + swipedSliderPosition: position - distance, }; }); setTimeout(() => { this.setState({ isSwiping: false, - swipedSliderPosition: 0 + swipedSliderPosition: 0, }); }, duration); }; - convertChildToCbObj = index => { + convertChildToCbObj = (index) => { const { children } = this.props; // support decimal itemsToShow const roundedIdx = Math.round(index); @@ -289,7 +299,7 @@ class Carousel extends React.Component { const { children, itemsToShow, - itemsToScroll + itemsToScroll, } = this.getDerivedPropsFromBreakPoint(); const childrenLength = Children.toArray(children).length; const notEnoughItemsToShow = itemsToShow > childrenLength; @@ -305,7 +315,7 @@ class Carousel extends React.Component { return nextItem; }; - getNextItemObj = getPrev => { + getNextItemObj = (getPrev) => { const { children } = this.props; const { activeIndex } = this.state; const nextItemIndex = this.getNextItemIndex(activeIndex, getPrev); @@ -320,25 +330,25 @@ class Carousel extends React.Component { this.setState({ swipedSliderPosition: 0, transitioning: false, - isSwiping: false + isSwiping: false, }); }; - onSwiping = data => { + onSwiping = (data) => { const { deltaX, absX, deltaY, absY, dir } = data; - this.setState(state => { + this.setState((state) => { const { rootHeight, activeIndex, sliderPosition, - sliderContainerWidth + sliderContainerWidth, } = state; const { itemsToShow, verticalMode, children, - isRTL + isRTL, } = this.getDerivedPropsFromBreakPoint(); // determine how far can user swipe @@ -386,12 +396,12 @@ class Carousel extends React.Component { ? sliderPosition - deltaX : sliderPosition - deltaY, isSwiping: true, - transitioning: true + transitioning: true, }; }); }; - onSwiped = data => { + onSwiped = (data) => { // we need to handle all scenarios: // 1. Horizontal mode - swipe left or right // 2. Horizontal mode with RTL - swipe left or right @@ -460,7 +470,7 @@ class Carousel extends React.Component { func({ skipTilt: true }); }; - onNextStart = options => { + onNextStart = (options) => { const { onNextStart } = this.props; const { activeIndex } = this.state; const nextItemObj = this.getNextItemObj(); @@ -469,7 +479,7 @@ class Carousel extends React.Component { this.slideNext(options); }; - onPrevStart = options => { + onPrevStart = (options) => { const { onPrevStart } = this.props; const { activeIndex } = this.state; const nextItemObj = this.getNextItemObj(true); @@ -522,12 +532,9 @@ class Carousel extends React.Component { onPrevEnd(nextItemObj, activePage); }; - generatePositionUpdater = ( - direction, - nextItemId, - verticalMode, - rest - ) => state => { + generatePositionUpdater = (direction, nextItemId, verticalMode, rest) => ( + state + ) => { const { sliderPosition, childWidth, childHeight, activeIndex } = state; let newSliderPosition = 0; const childSize = verticalMode ? childHeight : childWidth; @@ -544,15 +551,15 @@ class Carousel extends React.Component { activeIndex: nextItemId, swipedSliderPosition: 0, isSwiping: false, - ...rest + ...rest, }; }; - goTo = nextItemId => { + goTo = (nextItemId) => { const { children, verticalMode, - itemsToShow + itemsToShow, } = this.getDerivedPropsFromBreakPoint(); const { activeIndex } = this.state; const childrenLength = Children.toArray(children).length; @@ -578,15 +585,12 @@ class Carousel extends React.Component { nextItemId, verticalMode, { - transitioning: true + transitioning: true, } ); this.setState(stateUpdater, () => { // callback - pipe( - this.updateActivePage(), - this.onSliderTransitionEnd(positionEndCb) - ); + pipe(this.updateActivePage(), this.onSliderTransitionEnd(positionEndCb)); }); }; @@ -598,7 +602,7 @@ class Carousel extends React.Component { }; updateActivePage = () => { - this.setState(state => { + this.setState((state) => { const { itemsToShow } = this.getDerivedPropsFromBreakPoint(); const { activeIndex, activePage } = state; const newActivePage = Math.ceil(activeIndex / itemsToShow); @@ -608,7 +612,7 @@ class Carousel extends React.Component { }); }; - onIndicatorClick = indicatorId => { + onIndicatorClick = (indicatorId) => { const { itemsToShow } = this.getDerivedPropsFromBreakPoint(); const gotoIndex = indicatorId * itemsToShow; this.setState({ activePage: indicatorId }); @@ -625,7 +629,7 @@ class Carousel extends React.Component { rootHeight, pages, activeIndex, - transitionMs + transitionMs, } = this.state; const { className, @@ -647,7 +651,7 @@ class Carousel extends React.Component { disableArrowsOnEnd, preventDefaultTouchmoveEvent, renderArrow, - renderPagination + renderPagination, } = this.getDerivedPropsFromBreakPoint(); const numOfPages = this.getNumOfPages(); @@ -675,7 +679,7 @@ class Carousel extends React.Component { renderArrow({ type: consts.PREV, onClick: this.onPrevStart, - isEdge: !canSlidePrev + isEdge: !canSlidePrev, }) ) : ( {} */ - onResize: PropTypes.func + onResize: PropTypes.func, }; export default Carousel; From a74b418c65762bac79919c8f0054b3d09dd2bae2 Mon Sep 17 00:00:00 2001 From: "sagiv.bengiat" Date: Sun, 15 Nov 2020 10:29:48 +0200 Subject: [PATCH 2/4] fix gatsby infinite refresh --- package.json | 2 +- .../components/Carousel.js | 109 +++++++++--------- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 09f9c7d..956155a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-elastic-carousel", - "version": "0.9.4", + "version": "0.9.5-beta.1", "description": "A flexible and responsive carousel component for react", "author": "sag1v (Sagiv Ben Giat)", "license": "MIT", diff --git a/src/react-elastic-carousel/components/Carousel.js b/src/react-elastic-carousel/components/Carousel.js index 629ac41..cb115ab 100644 --- a/src/react-elastic-carousel/components/Carousel.js +++ b/src/react-elastic-carousel/components/Carousel.js @@ -11,7 +11,7 @@ import { SliderContainer, Slider, StyledCarousel, - CarouselWrapper, + CarouselWrapper } from "./styled"; import { pipe, noop, cssPrefix, numberToArray } from "../utils/helpers"; import { Pagination } from "./Pagination"; @@ -19,7 +19,6 @@ import { Pagination } from "./Pagination"; class Carousel extends React.Component { state = { rootHeight: 0, - rootWidth: 0, childWidth: 0, childHeight: 0, sliderPosition: 0, @@ -30,7 +29,7 @@ class Carousel extends React.Component { activeIndex: this.props.initialActiveIndex || this.props.initialFirstItem, // support deprecated initialFirstItem pages: [], activePage: 0, - sliderContainerWidth: 0, + sliderContainerWidth: 0 }; componentDidMount() { @@ -45,7 +44,7 @@ class Carousel extends React.Component { children, itemsToShow, itemsToScroll, - breakPoints, + breakPoints } = this.props; const { activeIndex, sliderContainerWidth } = this.state; const nextItem = this.getNextItemIndex(activeIndex, false); @@ -73,7 +72,7 @@ class Carousel extends React.Component { if (prevChildrenLength !== currentChildrenLength) { const { - itemsToShow: calculatedItemsToShow, + itemsToShow: calculatedItemsToShow } = this.getDerivedPropsFromBreakPoint(); // number of items is reduced (we don't care if number of items is increased) // we need to check if our current index is not out of boundaries @@ -91,7 +90,7 @@ class Carousel extends React.Component { this.unSubscribeObserver(); } - setRef = (name) => (ref) => (this[name] = ref); + setRef = name => ref => (this[name] = ref); initResizeObserver = () => { this.ro = new ResizeObserver((entries, observer) => { @@ -100,7 +99,7 @@ class Carousel extends React.Component { // we are using rAF because it fixes the infinite refresh with gatsby (ssr?). // TBH, I'm not sure i fully understand why. // see https://github.com/sag1v/react-elastic-carousel/issues/107 - requestAnimationFrame(() => { + window.requestAnimationFrame(() => { this.onContainerResize(entry); }); } @@ -108,7 +107,7 @@ class Carousel extends React.Component { // we are using rAF because it fixes the infinite refresh with gatsby (ssr?). // TBH, I'm not sure i fully understand why // see https://github.com/sag1v/react-elastic-carousel/issues/107 - requestAnimationFrame(() => { + window.requestAnimationFrame(() => { this.onSliderResize(entry); }); } @@ -144,11 +143,11 @@ class Carousel extends React.Component { this.setState({ pages }); }; - onSliderTransitionEnd = (fn) => { + onSliderTransitionEnd = fn => { this.slider.addEventListener("transitionend", fn); }; - removeSliderTransitionHook = (fn) => { + removeSliderTransitionHook = fn => { this.slider.removeEventListener("transitionend", fn); }; @@ -163,7 +162,7 @@ class Carousel extends React.Component { currentBreakPoint = breakPoints .slice() // no mutations .reverse() // so we can find last match - .find((bp) => bp.width <= sliderContainerWidth); + .find(bp => bp.width <= sliderContainerWidth); if (!currentBreakPoint) { /* in case we don't have a lower width than sliderContainerWidth * this mostly happens in initilization when sliderContainerWidth is 0 @@ -176,12 +175,12 @@ class Carousel extends React.Component { }; updateSliderPosition = () => { - this.setState((state) => { + this.setState(state => { const { children, verticalMode, itemsToShow, - transitionMs, + transitionMs } = this.getDerivedPropsFromBreakPoint(); const { childWidth, childHeight, activeIndex } = state; const totalItems = Children.toArray(children).length; @@ -200,16 +199,16 @@ class Carousel extends React.Component { window.requestAnimationFrame(() => this.setState({ transitionMs })); return { sliderPosition, - activeIndex: newActiveIndex < 0 ? 0 : newActiveIndex, + activeIndex: newActiveIndex < 0 ? 0 : newActiveIndex }; }); }; - onSliderResize = (sliderNode) => { + onSliderResize = sliderNode => { const { verticalMode, children, - itemsToShow, + itemsToShow } = this.getDerivedPropsFromBreakPoint(); const { height: sliderHeight } = sliderNode.contentRect; const nextState = {}; @@ -228,7 +227,7 @@ class Carousel extends React.Component { this.setState(nextState); }; - onContainerResize = (sliderContainerNode) => { + onContainerResize = sliderContainerNode => { const { width: sliderContainerWidth } = sliderContainerNode.contentRect; // update slider container width // disable animation on resize see https://github.com/sag1v/react-elastic-carousel/issues/94 @@ -238,7 +237,7 @@ class Carousel extends React.Component { onResize, verticalMode, itemsToShow, - children, + children } = this.getDerivedPropsFromBreakPoint(); /* based on slider container's width, get num of items to show @@ -257,7 +256,7 @@ class Carousel extends React.Component { } this.setState( - (state) => ({ childWidth }), + state => ({ childWidth }), () => { /* Based on all of the above new data: * update slider position @@ -273,21 +272,21 @@ class Carousel extends React.Component { }; tiltMovement = (position, distance = 20, duration = 150) => { - this.setState((state) => { + this.setState(state => { return { isSwiping: true, - swipedSliderPosition: position - distance, + swipedSliderPosition: position - distance }; }); setTimeout(() => { this.setState({ isSwiping: false, - swipedSliderPosition: 0, + swipedSliderPosition: 0 }); }, duration); }; - convertChildToCbObj = (index) => { + convertChildToCbObj = index => { const { children } = this.props; // support decimal itemsToShow const roundedIdx = Math.round(index); @@ -299,7 +298,7 @@ class Carousel extends React.Component { const { children, itemsToShow, - itemsToScroll, + itemsToScroll } = this.getDerivedPropsFromBreakPoint(); const childrenLength = Children.toArray(children).length; const notEnoughItemsToShow = itemsToShow > childrenLength; @@ -315,7 +314,7 @@ class Carousel extends React.Component { return nextItem; }; - getNextItemObj = (getPrev) => { + getNextItemObj = getPrev => { const { children } = this.props; const { activeIndex } = this.state; const nextItemIndex = this.getNextItemIndex(activeIndex, getPrev); @@ -330,25 +329,25 @@ class Carousel extends React.Component { this.setState({ swipedSliderPosition: 0, transitioning: false, - isSwiping: false, + isSwiping: false }); }; - onSwiping = (data) => { + onSwiping = data => { const { deltaX, absX, deltaY, absY, dir } = data; - this.setState((state) => { + this.setState(state => { const { rootHeight, activeIndex, sliderPosition, - sliderContainerWidth, + sliderContainerWidth } = state; const { itemsToShow, verticalMode, children, - isRTL, + isRTL } = this.getDerivedPropsFromBreakPoint(); // determine how far can user swipe @@ -396,12 +395,12 @@ class Carousel extends React.Component { ? sliderPosition - deltaX : sliderPosition - deltaY, isSwiping: true, - transitioning: true, + transitioning: true }; }); }; - onSwiped = (data) => { + onSwiped = data => { // we need to handle all scenarios: // 1. Horizontal mode - swipe left or right // 2. Horizontal mode with RTL - swipe left or right @@ -470,7 +469,7 @@ class Carousel extends React.Component { func({ skipTilt: true }); }; - onNextStart = (options) => { + onNextStart = options => { const { onNextStart } = this.props; const { activeIndex } = this.state; const nextItemObj = this.getNextItemObj(); @@ -479,7 +478,7 @@ class Carousel extends React.Component { this.slideNext(options); }; - onPrevStart = (options) => { + onPrevStart = options => { const { onPrevStart } = this.props; const { activeIndex } = this.state; const nextItemObj = this.getNextItemObj(true); @@ -532,9 +531,12 @@ class Carousel extends React.Component { onPrevEnd(nextItemObj, activePage); }; - generatePositionUpdater = (direction, nextItemId, verticalMode, rest) => ( - state - ) => { + generatePositionUpdater = ( + direction, + nextItemId, + verticalMode, + rest + ) => state => { const { sliderPosition, childWidth, childHeight, activeIndex } = state; let newSliderPosition = 0; const childSize = verticalMode ? childHeight : childWidth; @@ -551,15 +553,15 @@ class Carousel extends React.Component { activeIndex: nextItemId, swipedSliderPosition: 0, isSwiping: false, - ...rest, + ...rest }; }; - goTo = (nextItemId) => { + goTo = nextItemId => { const { children, verticalMode, - itemsToShow, + itemsToShow } = this.getDerivedPropsFromBreakPoint(); const { activeIndex } = this.state; const childrenLength = Children.toArray(children).length; @@ -585,12 +587,15 @@ class Carousel extends React.Component { nextItemId, verticalMode, { - transitioning: true, + transitioning: true } ); this.setState(stateUpdater, () => { // callback - pipe(this.updateActivePage(), this.onSliderTransitionEnd(positionEndCb)); + pipe( + this.updateActivePage(), + this.onSliderTransitionEnd(positionEndCb) + ); }); }; @@ -602,7 +607,7 @@ class Carousel extends React.Component { }; updateActivePage = () => { - this.setState((state) => { + this.setState(state => { const { itemsToShow } = this.getDerivedPropsFromBreakPoint(); const { activeIndex, activePage } = state; const newActivePage = Math.ceil(activeIndex / itemsToShow); @@ -612,7 +617,7 @@ class Carousel extends React.Component { }); }; - onIndicatorClick = (indicatorId) => { + onIndicatorClick = indicatorId => { const { itemsToShow } = this.getDerivedPropsFromBreakPoint(); const gotoIndex = indicatorId * itemsToShow; this.setState({ activePage: indicatorId }); @@ -629,7 +634,7 @@ class Carousel extends React.Component { rootHeight, pages, activeIndex, - transitionMs, + transitionMs } = this.state; const { className, @@ -651,7 +656,7 @@ class Carousel extends React.Component { disableArrowsOnEnd, preventDefaultTouchmoveEvent, renderArrow, - renderPagination, + renderPagination } = this.getDerivedPropsFromBreakPoint(); const numOfPages = this.getNumOfPages(); @@ -679,7 +684,7 @@ class Carousel extends React.Component { renderArrow({ type: consts.PREV, onClick: this.onPrevStart, - isEdge: !canSlidePrev, + isEdge: !canSlidePrev }) ) : ( {} */ - onResize: PropTypes.func, + onResize: PropTypes.func }; export default Carousel; From 22d6eff7456486d4bc3843df269fc17db87e61aa Mon Sep 17 00:00:00 2001 From: "sagiv.bengiat" Date: Sun, 15 Nov 2020 10:38:18 +0200 Subject: [PATCH 3/4] fix rtl swipe --- src/react-elastic-carousel/components/Carousel.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/react-elastic-carousel/components/Carousel.js b/src/react-elastic-carousel/components/Carousel.js index cb115ab..6e02103 100644 --- a/src/react-elastic-carousel/components/Carousel.js +++ b/src/react-elastic-carousel/components/Carousel.js @@ -390,10 +390,18 @@ class Carousel extends React.Component { // bail out of state update return; } + let swipedSliderPosition; + if (horizontalSwipe) { + if (isRTL) { + swipedSliderPosition = sliderPosition + deltaX; + } else { + swipedSliderPosition = sliderPosition - deltaX; + } + } else { + swipedSliderPosition = sliderPosition - deltaY; + } return { - swipedSliderPosition: horizontalSwipe - ? sliderPosition - deltaX - : sliderPosition - deltaY, + swipedSliderPosition, isSwiping: true, transitioning: true }; From 7262e18c9de67205e2135a40079f25f62b06dc2b Mon Sep 17 00:00:00 2001 From: "sagiv.bengiat" Date: Sun, 15 Nov 2020 10:41:15 +0200 Subject: [PATCH 4/4] bump tag version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 956155a..cf48da7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-elastic-carousel", - "version": "0.9.5-beta.1", + "version": "0.9.5-beta.2", "description": "A flexible and responsive carousel component for react", "author": "sag1v (Sagiv Ben Giat)", "license": "MIT",