From 4e4f97a1534c51f39ed80ae559bb2807a1426fa3 Mon Sep 17 00:00:00 2001 From: Vadym Shymko Date: Sun, 19 Feb 2023 21:03:36 +0200 Subject: [PATCH] Add new swipe options props --- README.md | 77 +++++++++++++++++++++++++++------------------------ src/index.tsx | 37 +++++++++++++++++++++---- 2 files changed, 73 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index a2f6ce7..70c2df7 100644 --- a/README.md +++ b/README.md @@ -131,42 +131,47 @@ export default ReactSimplyCarouselExample; ## Props -| 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 first argument and info about visible slides (`{`
` isFirstSlideVisible: boolean;`
`isLastSlideVisible: boolean;`
`visibleSlides: { slideIndex: number; isFullyVisible: boolean }[];`
`}`) as second. | -| **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 | `true` | Disable carousel forward nav if last slide is visible / Disable carousel backward nav if first slide is visible | -| **disableNavIfEdgeActive** | boolean | `true` | Disable carousel forward nav if activeSlideIndex === lastSlideIndex / Disable carousel backward nav if activeSlideIndex === 0 | -| **dotsNav** (experimental) | object | `{}` | Props for carousel dots. Includes `show` (boolean) property for toggle dots nav visibility, `containerProps` (DOM Props for dots nav wrapper div) property, `itemBtnProps` (DOM props for all dots nav buttons) property and `activeItemBtnProps` (DOM props for active dots nav button) | -| **persistentChangeCallbacks** | boolean | `false` | Enable call `onRequestChange` prop even if activeSlideIndex equals new value | -| **showSlidesBeforeInit** (deprecated) | boolean | `true` | Show slides on very first (initial) carousel render | -| **visibleSlideProps** | object | `{}` | DOM props for visible slide element | -| **autoplayDelay** | number | `0` | after what period of time the auto-update function of the active slide will be launched | -| **preventScrollOnSwipe** | boolean | `false` | prevent vertical scroll on swipe | -| **disableSwipeByMouse** | boolean | `false` | disable swipe by mouse | - -| **disableSwipeByTouch** | boolean | `false` | disable swipe by touch | +| 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 first argument and info about visible slides (`{`
` isFirstSlideVisible: boolean;`
`isLastSlideVisible: boolean;`
`visibleSlides: { slideIndex: number; isFullyVisible: boolean }[];`
`}`) as second. | +| **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 | `true` | Disable carousel forward nav if last slide is visible / Disable carousel backward nav if first slide is visible | +| **disableNavIfEdgeActive** | boolean | `true` | Disable carousel forward nav if activeSlideIndex === lastSlideIndex / Disable carousel backward nav if activeSlideIndex === 0 | +| **dotsNav** (experimental) | object | `{}` | Props for carousel dots. Includes `show` (boolean) property for toggle dots nav visibility, `containerProps` (DOM Props for dots nav wrapper div) property, `itemBtnProps` (DOM props for all dots nav buttons) property and `activeItemBtnProps` (DOM props for active dots nav button) | +| **persistentChangeCallbacks** | boolean | `false` | Enable call `onRequestChange` prop even if activeSlideIndex equals new value | +| **showSlidesBeforeInit** (deprecated) | boolean | `true` | Show slides on very first (initial) carousel render | +| **visibleSlideProps** | object | `{}` | DOM props for visible slide element | +| **autoplayDelay** | number | `0` | after what period of time the auto-update function of the active slide will be launched | +| **preventScrollOnSwipe** | boolean | `false` | prevent vertical scroll on swipe | +| **disableSwipeByMouse** | boolean | `false` | disable swipe by mouse | +| **disableSwipeByTouch** | boolean | `false` | disable swipe by touch | +| **swipeTreshold** | number | half width of the active slide | minimum swipe distance in px (by touch or by mouse drag) for change slide | +| **touchSwipeTreshold** | number | half width of the active slide | minimum swipe distance in px (by touch) for change slide | +| **mouseSwipeTreshold** | number | half width of the active slide | minimum swipe distance in px (by mouse drag) for change slide | +| **swipeRatio** | number | `1` | swipe distance ratio (on swipe by touchmove or by mouse drag) | +| **touchSwipeTreshold** | number | | swipe distance ratio (on swipe by touchmove) | +| **mouseSwipeTreshold** | number | | swipe distance ratio (on swipe by mouse drag) | ## Demo diff --git a/src/index.tsx b/src/index.tsx index 9589067..fc42f49 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -56,6 +56,8 @@ type ReactSimplyCarouselStaticProps = { itemsListProps?: HTMLAttributes; itemsToScroll?: number; itemsToShow?: number; + mouseSwipeRatio?: number; + mouseSwipeTreshold?: number; onAfterChange?: ( // eslint-disable-next-line no-unused-vars activeSlideIndex: number, @@ -72,6 +74,10 @@ type ReactSimplyCarouselStaticProps = { preventScrollOnSwipe?: boolean; showSlidesBeforeInit?: boolean; speed?: number; + swipeRatio?: number; + swipeTreshold?: number; + touchSwipeRatio?: number; + touchSwipeTreshold?: number; updateOnItemClick?: boolean; visibleSlideProps?: HTMLAttributes; }; @@ -179,6 +185,12 @@ function ReactSimplyCarousel({ preventScrollOnSwipe = false, disableSwipeByMouse = false, disableSwipeByTouch = false, + touchSwipeTreshold, + mouseSwipeTreshold, + swipeTreshold, + touchSwipeRatio, + mouseSwipeRatio, + swipeRatio = 1, } = windowWidth ? { ...propsByWindowWidth, @@ -670,8 +682,8 @@ function ReactSimplyCarousel({ : (event as MouseEvent).clientX; const dragPosDiff = - itemsListDragStartPosRef.current - - dragPos + + (itemsListDragStartPosRef.current - dragPos) * + ((isTouch ? touchSwipeRatio : mouseSwipeRatio) || swipeRatio) + offsetCorrectionForCenterMode + offsetCorrectionForInfiniteMode + (infinite ? 0 : itemsListTranslateX); @@ -703,16 +715,25 @@ function ReactSimplyCarousel({ ].clientX : (event as MouseEvent).clientX; - const mousePosDiff = itemsListDragStartPosRef.current - dragPos; + const mousePosDiff = + (itemsListDragStartPosRef.current - dragPos) * + ((isTouch ? touchSwipeRatio : mouseSwipeRatio) || swipeRatio); + + const activeSlideHalfWidth = activeSlideWidth / 2; + + const treshold = + (isTouch ? touchSwipeTreshold : mouseSwipeTreshold) || + swipeTreshold || + activeSlideHalfWidth; const nextActiveSlide = // eslint-disable-next-line no-nested-ternary - mousePosDiff > activeSlideWidth / 2 + mousePosDiff > treshold ? { index: getNextSlideIndex('forward'), direction: 'forward', } - : mousePosDiff < -activeSlideWidth / 2 + : mousePosDiff < -treshold ? { index: getNextSlideIndex('backward'), direction: 'backward', @@ -806,6 +827,12 @@ function ReactSimplyCarousel({ disableNav, disableSwipeByMouse, disableSwipeByTouch, + touchSwipeTreshold, + mouseSwipeTreshold, + swipeTreshold, + touchSwipeRatio, + mouseSwipeRatio, + swipeRatio, ]); useEffect(() => {