From 8d2f20813468209ca1f29cea04a61e141ea330a1 Mon Sep 17 00:00:00 2001 From: Vadym Shymko Date: Tue, 15 Jun 2021 00:14:36 +0300 Subject: [PATCH 1/3] Make infinite prop optional && fix small bugs with touch and mouse nav --- package.json | 2 +- src/index.jsx | 421 +++++++++++++++++++++++++++----------------------- 2 files changed, 228 insertions(+), 195 deletions(-) diff --git a/package.json b/package.json index a91af56..e1122bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-simply-carousel", - "version": "4.2.2", + "version": "5.0.0", "description": "Simple react.js carousel component", "main": "dist/index.js", "files": [ diff --git a/src/index.jsx b/src/index.jsx index 999d408..36afcb8 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -89,6 +89,9 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { disableNavIfAllVisible, hideNavIfAllVisible, centerMode, + infinite, + disableNavIfEdgeVisible, + disableNavIfEdgeActive, } = windowWidth ? { ...propsByWindowWidth, @@ -107,38 +110,24 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { } : props; - const slides = useMemo( - () => - windowWidth - ? [...itemsListRef.current.children].slice( - slidesItems.length - positionIndex, - slidesItems.length - positionIndex + slidesItems.length - ) - : [], - [positionIndex, slidesItems.length, windowWidth] - ); - - const getOffsetCorrectionForEdgeSlides = useCallback(() => { - if (positionIndex - activeSlideIndex === 0) { - return 0; + const slides = useMemo(() => { + if (!windowWidth) { + return []; } - if ( - directionRef.current.toLowerCase() === "forward" && - activeSlideIndex < positionIndex - ) { - return itemsListRef.current.offsetWidth / 3; + if (infinite) { + return [...itemsListRef.current.children].slice( + slidesItems.length - positionIndex, + slidesItems.length - positionIndex + slidesItems.length + ); } - if ( - directionRef.current.toLowerCase() === "backward" && - activeSlideIndex > positionIndex - ) { - return -itemsListRef.current.offsetWidth / 3; - } + return [...itemsListRef.current.children]; + }, [positionIndex, slidesItems.length, windowWidth, infinite]); - return 0; - }, [activeSlideIndex, positionIndex]); + const itemsListMaxTranslateX = windowWidth + ? itemsListRef.current.offsetWidth - innerRef.current.offsetWidth + : 0; const getItemsListOffsetBySlideIndex = (slideIndex) => { const offsetByIndex = slides.reduce((total, item, index) => { @@ -149,25 +138,32 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { return total + (item.offsetWidth || 0); }, 0); - return offsetByIndex; - }; + if (infinite) { + return offsetByIndex; + } - const innerMaxWidth = - !windowWidth || !itemsToShow - ? null - : slides.reduce((result, item, index) => { - const isItemVisible = - (index >= activeSlideIndex && - index < activeSlideIndex + itemsToShow) || - (index < activeSlideIndex && - index < activeSlideIndex + itemsToShow - slides.length); - - if (!isItemVisible) { - return result; - } + return Math.min(itemsListMaxTranslateX, offsetByIndex); + }; - return result + item.offsetWidth; - }, 0); + const innerMaxWidth = useMemo( + () => + !windowWidth || !itemsToShow + ? null + : slides.reduce((result, item, index) => { + const isItemVisible = + (index >= activeSlideIndex && + index < activeSlideIndex + itemsToShow) || + (index < activeSlideIndex && + index < activeSlideIndex + itemsToShow - slides.length); + + if (!isItemVisible) { + return result; + } + + return result + item.offsetWidth; + }, 0), + [activeSlideIndex, itemsToShow, slides, windowWidth] + ); const lastSlideIndex = Children.count(children) - 1; @@ -176,14 +172,14 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { const hideNav = hideNavIfAllVisible && isAllSlidesVisible; const disableNav = disableNavIfAllVisible && isAllSlidesVisible; - const isNewSLideIndex = activeSlideIndex - positionIndex !== 0; + const isNewSlideIndex = activeSlideIndex - positionIndex !== 0; const positionIndexOffset = - windowWidth && isNewSLideIndex + windowWidth && isNewSlideIndex && infinite ? getItemsListOffsetBySlideIndex(positionIndex) : 0; const activeSlideIndexOffset = - windowWidth && isNewSLideIndex + windowWidth && (isNewSlideIndex || !infinite) ? getItemsListOffsetBySlideIndex(activeSlideIndex) : 0; @@ -191,8 +187,9 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { ? slides[activeSlideIndex].offsetWidth : 0; - const ofsetCorrectionForCenterMode = - windowWidth && centerMode + const isCenterModeEnabled = centerMode && infinite; + const offsetCorrectionForCenterMode = + windowWidth && isCenterModeEnabled ? -( Math.min( innerMaxWidth || innerRef.current.offsetWidth, @@ -201,8 +198,29 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { ) / 2 : 0; + const slidesWidth = useMemo(() => { + if (infinite && windowWidth) { + return itemsListRef.current.offsetWidth / 3; + } + + return 0; + }, [windowWidth, infinite]); + + const offsetCorrectionForEdgeSlides = + // eslint-disable-next-line no-nested-ternary + positionIndex - activeSlideIndex === 0 || !itemsListRef.current + ? 0 + : // eslint-disable-next-line no-nested-ternary + directionRef.current.toLowerCase() === "forward" && + activeSlideIndex < positionIndex + ? slidesWidth + : directionRef.current.toLowerCase() === "backward" && + activeSlideIndex > positionIndex + ? -slidesWidth + : 0; + const itemsListTransition = - !isNewSLideIndex || !(speed || delay) + !isNewSlideIndex || !(speed || delay) ? null : `transform ${speed}ms ${easing} ${delay}ms`; const itemsListTranslateX = @@ -210,9 +228,9 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { ? 0 : activeSlideIndexOffset - positionIndexOffset + - ofsetCorrectionForCenterMode + - getOffsetCorrectionForEdgeSlides() + - itemsListRef.current.offsetWidth / 3; + offsetCorrectionForCenterMode + + offsetCorrectionForEdgeSlides + + slidesWidth; const itemsListTransform = windowWidth ? `translateX(-${itemsListTranslateX}px)` : null; @@ -222,8 +240,11 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { if (direction === "forward") { const nextSlideIndex = activeSlideIndex + itemsToScroll; const isOnEnd = nextSlideIndex > lastSlideIndex; + // eslint-disable-next-line no-nested-ternary const newSlideIndex = isOnEnd - ? nextSlideIndex - lastSlideIndex - 1 + ? infinite + ? nextSlideIndex - lastSlideIndex - 1 + : activeSlideIndex : nextSlideIndex; return newSlideIndex; @@ -232,8 +253,11 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { if (direction === "backward") { const nextSlideIndex = activeSlideIndex - itemsToScroll; const isOnStart = nextSlideIndex < 0; + // eslint-disable-next-line no-nested-ternary const newSlideIndex = isOnStart - ? lastSlideIndex + 1 + nextSlideIndex + ? infinite + ? lastSlideIndex + 1 + nextSlideIndex + : activeSlideIndex : nextSlideIndex; return newSlideIndex; @@ -241,17 +265,9 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { return activeSlideIndex; }, - [activeSlideIndex, itemsToScroll, lastSlideIndex] + [activeSlideIndex, itemsToScroll, lastSlideIndex, infinite] ); - const stopAutoplay = useCallback(() => { - clearTimeout(autoplayTimerRef.current); - }, []); - - const updatePositionIndex = useCallback(() => { - setPositionIndex(activeSlideIndex); - }, [activeSlideIndex]); - const updateActiveSlideIndex = useCallback( (newActiveSlideIndex, direction) => { directionRef.current = direction; @@ -259,31 +275,36 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { speed || delay ? `transform ${speed}ms ${easing} ${delay}ms` : null; if (newActiveSlideIndex !== activeSlideIndex) { - stopAutoplay(); + clearTimeout(autoplayTimerRef.current); onRequestChange(newActiveSlideIndex); } else { itemsListDragStartPosRef.current = null; isListDraggingRef.current = false; itemsListRef.current.style.transform = `translateX(-${ - ofsetCorrectionForCenterMode + itemsListRef.current.offsetWidth / 3 + offsetCorrectionForCenterMode + + slidesWidth + + (infinite ? 0 : itemsListTranslateX) }px)`; } }, [ activeSlideIndex, - ofsetCorrectionForCenterMode, + offsetCorrectionForCenterMode, delay, easing, speed, - stopAutoplay, onRequestChange, + slidesWidth, + infinite, + itemsListTranslateX, ] ); const startAutoplay = useCallback(() => { if (autoplay) { - stopAutoplay(); + clearTimeout(autoplayTimerRef.current); + autoplayTimerRef.current = setTimeout(() => { updateActiveSlideIndex( getNextSlideIndex(autoplayDirection), @@ -297,7 +318,6 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { updateActiveSlideIndex, getNextSlideIndex, delay, - stopAutoplay, ]); const handleContainerClickCapture = useCallback( @@ -318,13 +338,21 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { updateActiveSlideIndex(getNextSlideIndex("backward"), "backward"); }, [updateActiveSlideIndex, getNextSlideIndex]); - const updateItemsListPosByDragPos = useCallback( - (dragPos) => { + const handleItemsListDrag = useCallback( + (event) => { + isListDraggingRef.current = true; + + const dragPos = + event.touches && event.touches[0] + ? event.touches[0].clientX + : event.clientX; + const dragPosDiff = itemsListDragStartPosRef.current - dragPos + - ofsetCorrectionForCenterMode + - itemsListRef.current.offsetWidth / 3; + offsetCorrectionForCenterMode + + slidesWidth + + (infinite ? 0 : itemsListTranslateX); const minDragPos = 0; const maxDragPos = itemsListRef.current.offsetWidth - innerRef.current.offsetWidth; @@ -332,122 +360,96 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { Math.min(minDragPos, -dragPosDiff), -maxDragPos ); - - itemsListRef.current.style.transition = "none"; + itemsListRef.current.style.transition = null; itemsListRef.current.style.transform = `translateX(${itemsListPos}px)`; }, - [ofsetCorrectionForCenterMode] + [offsetCorrectionForCenterMode, slidesWidth, infinite, itemsListTranslateX] ); const handleItemsListDragEnd = useCallback( - (dragPos) => { - const mousePosDiff = itemsListDragStartPosRef.current - dragPos; - - if (mousePosDiff > activeSlideWidth / 2) { - updateActiveSlideIndex(getNextSlideIndex("forward"), "forward"); - } else if (mousePosDiff < -activeSlideWidth / 2) { - updateActiveSlideIndex(getNextSlideIndex("backward"), "backward"); - } else { - updateActiveSlideIndex(activeSlideIndex, "forward"); - } - }, - [ - activeSlideIndex, - activeSlideWidth, - updateActiveSlideIndex, - getNextSlideIndex, - ] - ); - - const handleItemsListMouseMove = useCallback( - (event) => { - isListDraggingRef.current = true; - - updateItemsListPosByDragPos(event.clientX); - }, - [updateItemsListPosByDragPos] - ); - - const handleItemsListMouseUp = useCallback( (event) => { itemsListRef.current.removeEventListener( "mouseout", - handleItemsListMouseUp + handleItemsListDragEnd ); itemsListRef.current.removeEventListener( "dragstart", - handleItemsListMouseUp + handleItemsListDragEnd ); - document.removeEventListener("mousemove", handleItemsListMouseMove); - document.removeEventListener("mouseup", handleItemsListMouseUp); + document.removeEventListener("mousemove", handleItemsListDrag); + document.removeEventListener("mouseup", handleItemsListDragEnd); + + document.removeEventListener("touchmove", handleItemsListDrag); + document.removeEventListener("touchend", handleItemsListDragEnd); if (isListDraggingRef.current) { - handleItemsListDragEnd(event.clientX); + const dragPos = + event.changedTouches && event.changedTouches.length + ? event.changedTouches[event.changedTouches.length - 1].clientX + : event.clientX; + + const mousePosDiff = itemsListDragStartPosRef.current - dragPos; + + if (mousePosDiff > activeSlideWidth / 2) { + updateActiveSlideIndex(getNextSlideIndex("forward"), "forward"); + } else if (mousePosDiff < -activeSlideWidth / 2) { + updateActiveSlideIndex(getNextSlideIndex("backward"), "backward"); + } else { + updateActiveSlideIndex(activeSlideIndex, "forward"); + } } }, - [handleItemsListDragEnd, handleItemsListMouseMove] + [ + activeSlideIndex, + activeSlideWidth, + updateActiveSlideIndex, + getNextSlideIndex, + handleItemsListDrag, + ] ); const handleItemsListMouseDown = useCallback( (event) => { - stopAutoplay(); + clearTimeout(autoplayTimerRef.current); if (!isListDraggingRef.current) { itemsListDragStartPosRef.current = event.clientX; - document.addEventListener("mousemove", handleItemsListMouseMove); - document.addEventListener("mouseup", handleItemsListMouseUp); + document.addEventListener("mousemove", handleItemsListDrag); + document.addEventListener("mouseup", handleItemsListDragEnd); itemsListRef.current.addEventListener( "mouseout", - handleItemsListMouseUp + handleItemsListDragEnd ); itemsListRef.current.addEventListener( "dragstart", - handleItemsListMouseUp - ); - } - }, - [handleItemsListMouseMove, handleItemsListMouseUp, stopAutoplay] - ); - - const handleItemsListTouchMove = useCallback( - (event) => { - isListDraggingRef.current = true; - updateItemsListPosByDragPos(event.touches[0].clientX); - }, - [updateItemsListPosByDragPos] - ); - - const handleItemsListTouchEnd = useCallback( - (event) => { - document.removeEventListener("touchmove", handleItemsListTouchMove); - document.removeEventListener("touchend", handleItemsListTouchEnd); - - if (isListDraggingRef.current) { - handleItemsListDragEnd( - event.changedTouches[event.changedTouches.length - 1].clientX + handleItemsListDragEnd ); } }, - [handleItemsListDragEnd, handleItemsListTouchMove] + [handleItemsListDrag, handleItemsListDragEnd] ); const handleItemsListTouchStart = useCallback( (event) => { - stopAutoplay(); + clearTimeout(autoplayTimerRef.current); if (!isListDraggingRef.current) { itemsListDragStartPosRef.current = event.touches[0].clientX; - document.addEventListener("touchmove", handleItemsListTouchMove); - document.addEventListener("touchend", handleItemsListTouchEnd); + document.addEventListener("touchmove", handleItemsListDrag); + document.addEventListener("touchend", handleItemsListDragEnd); } }, - [handleItemsListTouchMove, handleItemsListTouchEnd, stopAutoplay] + [handleItemsListDrag, handleItemsListDragEnd] ); + const handleItemsListTransitionEnd = useCallback(() => { + setPositionIndex(activeSlideIndex); + }, [activeSlideIndex]); + const handleForwardBtnClick = useCallback(() => { updateActiveSlideIndex(getNextSlideIndex("forward"), "forward"); }, [updateActiveSlideIndex, getNextSlideIndex]); @@ -482,14 +484,18 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { ...slideComponentData } = item; - const direction = - renderedSlidesCountRef.current >= slidesItems.length + // eslint-disable-next-line no-nested-ternary + const direction = infinite + ? renderedSlidesCountRef.current >= slidesItems.length ? "forward" - : "backward"; + : "backward" + : index >= activeSlideIndex + ? "forward" + : "backward"; const isActive = index + startIndex === activeSlideIndex; - const className = `${itemClassName} ${ + const className = `${itemClassName} ${direction} ${ isActive ? activeSlideClassName : "" }`; const style = { @@ -523,17 +529,6 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { }; }); - const updateWindowWidth = useCallback(() => { - setWindowWidth(window.innerWidth); - }, []); - - const handleWindowResize = useCallback(() => { - clearTimeout(resizeTimerRef.current); - stopAutoplay(); - - resizeTimerRef.current = setTimeout(updateWindowWidth, 400); - }, [updateWindowWidth, stopAutoplay]); - useEffect(() => { itemsListDragStartPosRef.current = null; isListDraggingRef.current = false; @@ -541,18 +536,25 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { if (activeSlideIndex !== positionIndex) { if (!speed && !delay) { - updatePositionIndex(); + setPositionIndex(activeSlideIndex); } } else { if (onAfterChange) { onAfterChange(activeSlideIndex, positionIndex); } - startAutoplay(); + if ( + infinite || + (autoplayDirection === "forward" && + activeSlideIndex !== lastSlideIndex) || + (autoplayDirection === "backward" && activeSlideIndex !== 0) + ) { + startAutoplay(); + } } return () => { - stopAutoplay(); + clearTimeout(autoplayTimerRef.current); }; }, [ positionIndex, @@ -560,25 +562,35 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { onAfterChange, speed, delay, - updatePositionIndex, startAutoplay, - stopAutoplay, + infinite, + lastSlideIndex, + autoplayDirection, ]); useEffect(() => { - if (windowWidth && !autoplayTimerRef.current) { + if (windowWidth) { startAutoplay(); } return () => { - stopAutoplay(); + clearTimeout(autoplayTimerRef.current); }; - }, [windowWidth, stopAutoplay, startAutoplay]); + }, [windowWidth]); useEffect(() => { const itemsListRefDOMElement = itemsListRef.current; - updateWindowWidth(); + function handleWindowResize() { + clearTimeout(resizeTimerRef.current); + clearTimeout(autoplayTimerRef.current); + + resizeTimerRef.current = setTimeout(() => { + setWindowWidth(window.innerWidth); + }, 400); + } + + setWindowWidth(window.innerWidth); window.addEventListener("resize", handleWindowResize); @@ -586,31 +598,29 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { clearTimeout(resizeTimerRef.current); window.removeEventListener("resize", handleWindowResize); - document.removeEventListener("mousemove", handleItemsListMouseMove); - document.removeEventListener("mouseup", handleItemsListMouseUp); - document.removeEventListener("touchmove", handleItemsListTouchMove); - document.removeEventListener("touchend", handleItemsListTouchEnd); + document.removeEventListener("mousemove", handleItemsListDrag); + document.removeEventListener("mouseup", handleItemsListDragEnd); + document.removeEventListener("touchmove", handleItemsListDrag); + document.removeEventListener("touchend", handleItemsListDragEnd); itemsListRefDOMElement.removeEventListener( "mouseout", - handleItemsListMouseUp + handleItemsListDragEnd ); itemsListRefDOMElement.removeEventListener( "dragstart", - handleItemsListMouseUp + handleItemsListDragEnd ); }; - }, [ - handleItemsListMouseMove, - handleWindowResize, - handleItemsListMouseUp, - handleItemsListTouchMove, - handleItemsListTouchEnd, - updateWindowWidth, - ]); + }, [handleItemsListDrag, handleItemsListDragEnd]); renderedSlidesCountRef.current = 0; + // IT IS TEMPORARY + if (windowWidth) { + itemsListRef.current.style.transform = itemsListTransform; + } + return (
{backwardBtnChildren} )}
{/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events */}
{!disableNav && + infinite && renderSlidesItems(slidesItems.slice(positionIndex), positionIndex)} {renderSlidesItems(slidesItems, 0, disableNav)} - {!disableNav && renderSlidesItems(slidesItems, 0)} + {!disableNav && infinite && renderSlidesItems(slidesItems, 0)} {!disableNav && + infinite && renderSlidesItems(slidesItems.slice(0, positionIndex), 0)}
@@ -682,7 +701,15 @@ function ReactSimplyCarousel({ responsiveProps, ...props }) { // eslint-disable-next-line react/jsx-props-no-spreading {...forwardBtnProps} type="button" - onClick={handleForwardBtnClick} + onClick={ + ((itemsListTranslateX === itemsListMaxTranslateX && + disableNavIfEdgeVisible) || + (activeSlideIndex === lastSlideIndex && + disableNavIfEdgeActive)) && + !infinite + ? null + : handleForwardBtnClick + } > {forwardBtnChildren} @@ -714,6 +741,9 @@ ReactSimplyCarousel.propTypes = { speed: PropTypes.number, updateOnItemClick: PropTypes.bool, centerMode: PropTypes.bool, + infinite: PropTypes.bool, + disableNavIfEdgeVisible: PropTypes.bool, + disableNavIfEdgeActive: PropTypes.bool, }; ReactSimplyCarousel.defaultProps = { @@ -737,6 +767,9 @@ ReactSimplyCarousel.defaultProps = { speed: 0, updateOnItemClick: false, centerMode: false, + infinite: true, + disableNavIfEdgeVisible: true, + disableNavIfEdgeActive: true, }; export default memo(ReactSimplyCarousel); From 729d998fa3bad4d2f3c3f8e0a62ccfa7f10c054b Mon Sep 17 00:00:00 2001 From: Vadym Shymko Date: Tue, 15 Jun 2021 00:35:22 +0300 Subject: [PATCH 2/3] Update docs --- README.md | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index a0226e3..dbdd1fa 100644 --- a/README.md +++ b/README.md @@ -72,30 +72,33 @@ class App extends Component { ## Props -| Name | Type | Default Value | Description | -| ---------------------- | -------------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| activeSlideIndex | number | | Index of first visible children (slide) | -| activeSlideProps | object | {} | DOM props for first visible slide element | -| autoplay | boolean | false | Boolean indicating if the carousel should be updated automatically | -| autoplayDirection | string ('forward' or 'backward') | 'forward' | Direction of autoplay updates | -| backwardBtnProps | object | {} | Contain DOM props for carousel backward button element, boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens) | -| children | node | null | Array of slides | -| containerProps | object | {} | DOM props for container div element | -| delay | number | 0 | Slide change delay (css transition delay) in ms | -| disableNavIfAllVisible | boolean | true | Boolean indicating if the carousel nav (by nav buttons, click on slide item, mouse move or touch move) should be disabled if all slides is visible | -| easing | string | 'linear' | Slide change easing (css transition easing) | -| forwardBtnProps | object | {} | Contain DOM props for carousel forward button element, boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens) | -| hideNavIfAllVisible | boolean | true | Boolean indicating if the carousel nav buttons should be hidden if all slides is visible | -| innerProps | object | {} | DOM props for inner div element | -| itemsListProps | object | {} | DOM props for items list div element | -| itemsToScroll | number | 1 | number of slides that should be scrolled to hidden part of carousel | -| itemsToShow | number | 0 (automaticaly calculated) | number of slides that should be visible | -| onAfterChange | function | null | Function that will be run after all updates is done and carousel moving is end | -| onRequestChange | function | | Function that will be run when the activeSlideIndex is requested to be changed (either by clicking on navigation button, clicking on slide (if prop `updateOnItemClick` value is `true` ), or after drag slides) | -| responsiveProps | Array of objects | [] | carousel props for different window width. For example: `[{minWidth: 768, maxWidth: 992, itemsToShow: 3}, {maxWidth: 767, itemsToShow: 1}]` will show only one slide when window width is less than 767px and show 3 slides when window width is >= 768px and < 992px | -| speed | number | 0 | Slide change speed (css transition speed) in ms | -| updateOnItemClick | boolean | false | Boolean indicating if the `onRequestChange` prop should be called after click on some slide | -| centerMode | boolean | false | Boolean indicating if the active slide should be aligned to center of container viewport | +| Name | Type | Default Value | Description | +| ----------------------------------------------------- | -------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **activeSlideIndex** | number | | Index of first visible children (slide) | +| **activeSlideProps** | object | `{}` | DOM props for first visible slide element | +| **autoplay** | boolean | `false` | Boolean indicating if the carousel should be updated automatically | +| **autoplayDirection** | string ('forward' or 'backward') | `'forward'` | Direction of autoplay updates | +| **backwardBtnProps** | object | `{}` | Contain DOM props for carousel backward button element, boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens) | +| **children** | node | `null` | Array of slides | +| **containerProps** | object | `{}` | DOM props for container div element | +| **delay** | number | `0` | Slide change delay (css transition delay) in ms | +| **disableNavIfAllVisible** | boolean | `true` | Boolean indicating if the carousel nav (by nav buttons, click on slide item, mouse move or touch move) should be disabled if all slides is visible | +| **easing** | string | `'linear'` | Slide change easing (css transition easing) | +| **forwardBtnProps** | object | `{}` | Contain DOM props for carousel forward button element, boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens) | +| **hideNavIfAllVisible** | boolean | `true` | Boolean indicating if the carousel nav buttons should be hidden if all slides is visible | +| **innerProps** | object | `{}` | DOM props for inner div element | +| **itemsListProps** | object | `{}` | DOM props for items list div element | +| **itemsToScroll** | number | `1` | number of slides that should be scrolled to hidden part of carousel | +| **itemsToShow** | number | `0` (automaticaly calculated) | number of slides that should be visible | +| **onAfterChange** | function | `null` | Function that will be run after all updates is done and carousel moving is end | +| **onRequestChange** | function | | Function that will be run when the activeSlideIndex is requested to be changed (either by clicking on navigation button, clicking on slide (if prop `updateOnItemClick` value is `true` ), or after drag slides) | +| **responsiveProps** | Array of objects | `[]` | carousel props for different window width. For example: `[{minWidth: 768, maxWidth: 992, itemsToShow: 3}, {maxWidth: 767, itemsToShow: 1}]` will show only one slide when window width is less than 767px and show 3 slides when window width is >= 768px and < 992px | +| **speed** | number | `0` | Slide change speed (css transition speed) in ms | +| **updateOnItemClick** | boolean | `false` | Boolean indicating if the `onRequestChange` prop should be called after click on some slide | +| **centerMode** (disabled if `infinite` prop disabled) | boolean | `false` | Boolean indicating if the active slide should be aligned to center of container viewport | +| **infinite** | boolean | `false` | Boolean indicating | +| **disableNavIfEdgeVisible** | boolean | `false` | Boolean indicating | +| **disableNavIfEdgeActive** | boolean | `false` | Boolean indicating | ## Demo From c8be725b656cb1b5095f1f1f6383e4ca58262611 Mon Sep 17 00:00:00 2001 From: Vadym Shymko Date: Tue, 15 Jun 2021 17:26:26 +0300 Subject: [PATCH 3/3] Update docs --- README.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index dbdd1fa..d681280 100644 --- a/README.md +++ b/README.md @@ -72,33 +72,33 @@ class App extends Component { ## Props -| Name | Type | Default Value | Description | -| ----------------------------------------------------- | -------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **activeSlideIndex** | number | | Index of first visible children (slide) | -| **activeSlideProps** | object | `{}` | DOM props for first visible slide element | -| **autoplay** | boolean | `false` | Boolean indicating if the carousel should be updated automatically | -| **autoplayDirection** | string ('forward' or 'backward') | `'forward'` | Direction of autoplay updates | -| **backwardBtnProps** | object | `{}` | Contain DOM props for carousel backward button element, boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens) | -| **children** | node | `null` | Array of slides | -| **containerProps** | object | `{}` | DOM props for container div element | -| **delay** | number | `0` | Slide change delay (css transition delay) in ms | -| **disableNavIfAllVisible** | boolean | `true` | Boolean indicating if the carousel nav (by nav buttons, click on slide item, mouse move or touch move) should be disabled if all slides is visible | -| **easing** | string | `'linear'` | Slide change easing (css transition easing) | -| **forwardBtnProps** | object | `{}` | Contain DOM props for carousel forward button element, boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens) | -| **hideNavIfAllVisible** | boolean | `true` | Boolean indicating if the carousel nav buttons should be hidden if all slides is visible | -| **innerProps** | object | `{}` | DOM props for inner div element | -| **itemsListProps** | object | `{}` | DOM props for items list div element | -| **itemsToScroll** | number | `1` | number of slides that should be scrolled to hidden part of carousel | -| **itemsToShow** | number | `0` (automaticaly calculated) | number of slides that should be visible | -| **onAfterChange** | function | `null` | Function that will be run after all updates is done and carousel moving is end | -| **onRequestChange** | function | | Function that will be run when the activeSlideIndex is requested to be changed (either by clicking on navigation button, clicking on slide (if prop `updateOnItemClick` value is `true` ), or after drag slides) | -| **responsiveProps** | Array of objects | `[]` | carousel props for different window width. For example: `[{minWidth: 768, maxWidth: 992, itemsToShow: 3}, {maxWidth: 767, itemsToShow: 1}]` will show only one slide when window width is less than 767px and show 3 slides when window width is >= 768px and < 992px | -| **speed** | number | `0` | Slide change speed (css transition speed) in ms | -| **updateOnItemClick** | boolean | `false` | Boolean indicating if the `onRequestChange` prop should be called after click on some slide | -| **centerMode** (disabled if `infinite` prop disabled) | boolean | `false` | Boolean indicating if the active slide should be aligned to center of container viewport | -| **infinite** | boolean | `false` | Boolean indicating | -| **disableNavIfEdgeVisible** | boolean | `false` | Boolean indicating | -| **disableNavIfEdgeActive** | boolean | `false` | Boolean indicating | +| Name | Type | Default Value | Description | +| ----------------------------------------------------------------- | ------------------------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **activeSlideIndex** | number | | Index of active slide | +| **activeSlideProps** | object | `{}` | DOM props for active slide element | +| **autoplay** | boolean | `false` | | +| **autoplayDirection** | string (`'forward'` or `'backward'`) | `'forward'` | | +| **backwardBtnProps** | object | `{}` | DOM props for carousel backward nav button element (include boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens)) | +| **children** | node | `null` | slides array | +| **containerProps** | object | `{}` | DOM props for carousel container div element | +| **delay** | number | `0` | Slide change delay (css transition delay) in ms | +| **disableNavIfAllVisible** | boolean | `true` | Disable carousel nav if all slides is visible | +| **easing** | string | `'linear'` | Slide change easing (css transition easing) | +| **forwardBtnProps** | object | `{}` | DOM props for carousel forward nav button element (include boolean prop `show` (for toggle button render) and node prop `children` (for render button childrens)) | +| **hideNavIfAllVisible** | boolean | `true` | Hide nav buttons if all slides is visible | +| **innerProps** | object | `{}` | DOM props for inner div element | +| **itemsListProps** | object | `{}` | DOM props for items list div element | +| **itemsToScroll** | number | `1` | How many slides to scroll at once | +| **itemsToShow** | number | `0` (automaticaly calculated) | How many slides to show | +| **onAfterChange** | function | `null` | activeSlideIndex change callback | +| **onRequestChange** | function | | Callback to handle every time the active slide changes, receives the new active index as arguments. | +| **responsiveProps** | Array of objects | `[]` | carousel props for different window width. For example: `[{minWidth: 768, maxWidth: 992, itemsToShow: 3}, {maxWidth: 767, itemsToShow: 1}]` will show only one slide when window width is less than 767px and show 3 slides when window width is >= 768px and < 992px | +| **speed** | number | `0` | Carousel scroll speed (css transition speed) in ms | +| **updateOnItemClick** | boolean | `false` | Update active item index after click on some slide | +| **centerMode** (disabled if `infinite` prop disabled) | boolean | `false` | Align active slide to the center of the carousel container viewport | +| **infinite** | boolean | `true` | Enable infinite loop scroll | +| **disableNavIfEdgeVisible** (disabled if `infinite` prop enabled) | boolean | `false` | Disable carousel forward nav if last slide is visible / Disable carousel backward nav if first slide is visible | +| **disableNavIfEdgeActive** | boolean | `false` | Disable carousel forward nav if activeSlideIndex === lastSlideIndex / Disable carousel backward nav if activeSlideIndex === 0 | ## Demo