react-multi-carousel
Advanced tools
import * as React from "react"; | ||
import { CarouselProps } from "./types"; | ||
declare const Carousel: ({ children, ...rest }: CarouselProps) => React.ReactNode; | ||
import { CarouselInternalState, CarouselProps } from "./types"; | ||
declare class Carousel extends React.Component<CarouselProps, CarouselInternalState> { | ||
static defaultProps: any; | ||
private readonly containerRef; | ||
onMove: boolean; | ||
initialPosition: number; | ||
lastPosition: number; | ||
isAnimationAllowed: boolean; | ||
direction: string; | ||
autoPlay?: any; | ||
constructor(props: CarouselProps); | ||
componentDidMount(): void; | ||
setItemsToShow(shouldCorrectItemPosition?: boolean): void; | ||
setContainerAndItemWidth(slidesToShow: number, shouldCorrectItemPosition?: boolean): void; | ||
onResize(): void; | ||
componentDidUpdate({ keyBoardControl, autoPlay }: CarouselProps, { containerWidth }: CarouselInternalState): void; | ||
resetAllItems(): void; | ||
next(slidesHavePassed?: number): void; | ||
previous(slidesHavePassed?: number): void; | ||
componentWillUnmount(): void; | ||
resetMoveStatus(): void; | ||
handleDown(e: any): void; | ||
handleMove(e: any): void; | ||
handleOut(e: any): void; | ||
onKeyUp(e: any): void; | ||
handleEnter(): void; | ||
renderLeftArrow(): React.ReactElement<any>; | ||
renderRightArrow(): React.ReactElement<any>; | ||
render(): React.ReactNode; | ||
} | ||
export default Carousel; |
"use strict"; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) | ||
t[p[i]] = s[p[i]]; | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -17,3 +8,3 @@ const React = require("react"); | ||
const defaultTransition = "transform 300ms ease-in-out"; | ||
class Container extends React.Component { | ||
class Carousel extends React.Component { | ||
constructor(props) { | ||
@@ -33,9 +24,9 @@ super(props); | ||
this.onResize = this.onResize.bind(this); | ||
this.handleMouseDown = this.handleMouseDown.bind(this); | ||
this.handleMouseMove = this.handleMouseMove.bind(this); | ||
this.handleMouseUp = this.handleMouseUp.bind(this); | ||
this.handleTouchStart = this.handleTouchStart.bind(this); | ||
this.handleTouchMove = this.handleTouchMove.bind(this); | ||
this.handleTouchEnd = this.handleTouchEnd.bind(this); | ||
this.handleDown = this.handleDown.bind(this); | ||
this.handleMove = this.handleMove.bind(this); | ||
this.handleOut = this.handleOut.bind(this); | ||
this.onKeyUp = this.onKeyUp.bind(this); | ||
this.handleEnter = this.handleEnter.bind(this); | ||
this.next = this.next.bind(this); | ||
this.previous = this.previous.bind(this); | ||
this.onMove = false; | ||
@@ -55,2 +46,5 @@ this.initialPosition = 0; | ||
} | ||
if (this.props.autoPlay && this.props.autoPlaySpeed) { | ||
this.autoPlay = setInterval(this.next, this.props.autoPlaySpeed); | ||
} | ||
} | ||
@@ -86,3 +80,3 @@ setItemsToShow(shouldCorrectItemPosition) { | ||
} | ||
componentDidUpdate(prevProps, { containerWidth }) { | ||
componentDidUpdate({ keyBoardControl, autoPlay }, { containerWidth }) { | ||
if (this.containerRef && | ||
@@ -95,2 +89,12 @@ this.containerRef.current && | ||
} | ||
if (keyBoardControl && !this.props.keyBoardControl) { | ||
window.removeEventListener("keyup", this.onKeyUp); | ||
} | ||
if (autoPlay && !this.props.autoPlay && this.autoPlay) { | ||
clearInterval(this.autoPlay); | ||
this.autoPlay = undefined; | ||
} | ||
if (!autoPlay && this.props.autoPlay && !this.autoPlay) { | ||
this.autoPlay = setInterval(this.next, this.props.autoPlaySpeed); | ||
} | ||
} | ||
@@ -115,3 +119,3 @@ resetAllItems() { | ||
this.state.currentSlide + 1 + slidesToShow <= this.state.totalItems) { | ||
// prevent over sliding; | ||
// prevent oversliding; | ||
const maxSlides = this.state.totalItems - slidesToShow; | ||
@@ -167,2 +171,6 @@ const maxPosition = -(this.state.itemWidth * maxSlides); | ||
} | ||
if (this.props.autoPlay && this.autoPlay) { | ||
clearInterval(this.autoPlay); | ||
this.autoPlay = undefined; | ||
} | ||
} | ||
@@ -175,20 +183,25 @@ resetMoveStatus() { | ||
} | ||
handleMouseDown(e) { | ||
if (this.props.disableDrag) { | ||
handleDown(e) { | ||
if ((e.touches && this.props.disableSwipeOnMobile) || | ||
(e && !e.touches && this.props.disableDrag)) { | ||
return; | ||
} | ||
const { clientX } = e.touches ? e.touches[0] : e; | ||
this.onMove = true; | ||
this.initialPosition = e.pageX; | ||
this.lastPosition = e.pageX; | ||
this.initialPosition = clientX; | ||
this.lastPosition = clientX; | ||
this.isAnimationAllowed = false; | ||
} | ||
handleMouseMove(e) { | ||
if (this.props.disableDrag) { | ||
handleMove(e) { | ||
if ((e.touches && this.props.disableSwipeOnMobile) || | ||
(e && !e.touches && this.props.disableDrag)) { | ||
return; | ||
} | ||
const { clientX } = e.touches ? e.touches[0] : e; | ||
if (this.onMove) { | ||
if (this.initialPosition > e.pageX) { | ||
if (this.initialPosition > clientX) { | ||
this.direction = "right"; | ||
const translateXLimit = Math.abs(-(this.state.itemWidth * | ||
(this.state.totalItems - this.state.slidesToShow))); | ||
const nextTranslate = this.state.transform - (this.lastPosition - e.pageX); | ||
const nextTranslate = this.state.transform - (this.lastPosition - clientX); | ||
const isLastSlide = this.state.currentSlide === | ||
@@ -201,4 +214,5 @@ this.state.totalItems - this.state.slidesToShow; | ||
} | ||
if (e.pageX > this.initialPosition) { | ||
const nextTranslate = this.state.transform + (e.pageX - this.lastPosition); | ||
if (clientX > this.initialPosition) { | ||
this.direction = "left"; | ||
const nextTranslate = this.state.transform + (clientX - this.lastPosition); | ||
const isFirstSlide = this.state.currentSlide === 0; | ||
@@ -209,70 +223,23 @@ if (nextTranslate <= 0 || (isFirstSlide && this.props.infinite)) { | ||
} | ||
this.lastPosition = e.pageX; | ||
this.lastPosition = clientX; | ||
} | ||
} | ||
handleMouseUp(e) { | ||
if (this.props.disableDrag) { | ||
return; | ||
handleOut(e) { | ||
if (this.props.autoPlay && !this.autoPlay) { | ||
this.autoPlay = setInterval(this.next, this.props.autoPlaySpeed); | ||
} | ||
if (this.onMove) { | ||
if (this.initialPosition > e.pageX) { | ||
const hasTravel = Math.round((this.initialPosition - e.pageX) / this.state.itemWidth); | ||
this.next(hasTravel); | ||
} | ||
if (e.pageX > this.initialPosition) { | ||
const hasTravel = Math.round((e.pageX - this.initialPosition) / this.state.itemWidth); | ||
this.previous(hasTravel); | ||
} | ||
this.resetMoveStatus(); | ||
} | ||
} | ||
handleTouchStart(e) { | ||
if (this.props.disableSwipeOnMobile) { | ||
const shouldDisableOnMobile = e.type === "touchend" && this.props.disableSwipeOnMobile; | ||
const shouldDisableOnDesktop = (e.type === "mouseleave" || e.type === "mouseup") && | ||
this.props.disableDrag; | ||
if (shouldDisableOnMobile || shouldDisableOnDesktop) { | ||
return; | ||
} | ||
this.onMove = true; | ||
this.initialPosition = e.touches[0].screenX; | ||
this.lastPosition = e.touches[0].screenX; | ||
this.isAnimationAllowed = false; | ||
} | ||
handleTouchMove(e) { | ||
if (this.props.disableSwipeOnMobile) { | ||
return; | ||
} | ||
if (this.onMove) { | ||
if (this.initialPosition > e.touches[0].screenX) { | ||
this.direction = "right"; | ||
const translateXLimit = Math.abs(-(this.state.itemWidth * | ||
(this.state.totalItems - this.state.slidesToShow))); | ||
const nextTranslate = this.state.transform - (this.lastPosition - e.touches[0].screenX); | ||
const isLastSlide = this.state.currentSlide === | ||
this.state.totalItems - this.state.slidesToShow; | ||
if (Math.abs(nextTranslate) <= translateXLimit || (isLastSlide && this.props.infinite)) { | ||
this.setState({ transform: nextTranslate }); | ||
} | ||
} | ||
if (e.touches[0].screenX > this.initialPosition) { | ||
this.direction = "left"; | ||
const nextTranslate = this.state.transform + (e.touches[0].screenX - this.lastPosition); | ||
const isFirstSlide = this.state.currentSlide === 0; | ||
if (nextTranslate <= 0 || (isFirstSlide && this.props.infinite)) { | ||
this.setState({ transform: nextTranslate }); | ||
} | ||
} | ||
this.lastPosition = e.touches[0].screenX; | ||
} | ||
} | ||
handleTouchEnd() { | ||
if (this.props.disableSwipeOnMobile) { | ||
return; | ||
} | ||
this.isAnimationAllowed = true; | ||
if (this.onMove) { | ||
if (this.direction === "right") { | ||
const hasTravel = Math.round((this.initialPosition - this.lastPosition) / this.state.itemWidth); | ||
this.next(hasTravel); | ||
const slidesHavePassed = Math.round((this.initialPosition - this.lastPosition) / this.state.itemWidth); | ||
this.next(slidesHavePassed); | ||
} | ||
if (this.direction === "left") { | ||
const hasTravel = Math.round((this.lastPosition - this.initialPosition) / this.state.itemWidth); | ||
this.previous(hasTravel); | ||
const slidesHavePassed = Math.round((this.lastPosition - this.initialPosition) / this.state.itemWidth); | ||
this.previous(slidesHavePassed); | ||
} | ||
@@ -290,2 +257,8 @@ this.resetMoveStatus(); | ||
} | ||
handleEnter() { | ||
if (this.autoPlay && this.props.autoPlay) { | ||
clearInterval(this.autoPlay); | ||
this.autoPlay = undefined; | ||
} | ||
} | ||
renderLeftArrow() { | ||
@@ -319,9 +292,9 @@ const { customLeftArrow } = this.props; | ||
const { domLoaded, slidesToShow, containerWidth, itemWidth } = this.state; | ||
const { deviceType, responsive, forSSR, children, slidesToSlide, customLeftArrow, customRightArrow, disableSwipeOnMobile, removeArrow, removeArrowOnDeviceType, infinite, containerClassName, contentClassName, itemClassName, customTransition } = this.props; | ||
const { deviceType, responsive, forSSR, children, slidesToSlide, removeArrow, removeArrowOnDeviceType, infinite, containerClassName, contentClassName, itemClassName, customTransition } = this.props; | ||
let flexBisis; | ||
const domFullLoaded = domLoaded && slidesToShow && containerWidth && itemWidth; | ||
if (forSSR && deviceType && !domFullLoaded) { | ||
const domFullyLoaded = domLoaded && slidesToShow && containerWidth && itemWidth; | ||
if (forSSR && deviceType && !domFullyLoaded) { | ||
flexBisis = utils_1.guessWidthFromDeviceType(deviceType, responsive); | ||
} | ||
const shouldRenderOnSSR = forSSR && deviceType && !domFullLoaded && flexBisis; | ||
const shouldRenderOnSSR = forSSR && deviceType && !domFullyLoaded && flexBisis; | ||
const isLeftEndReach = !(this.state.currentSlide - slidesToSlide >= 0); | ||
@@ -342,5 +315,5 @@ const isRightEndReach = !(this.state.currentSlide + 1 + slidesToShow <= | ||
? customTransition || defaultTransition | ||
: "none", overflow: shouldRenderOnSSR ? "hidden" : "unset", transform: `translate3d(${this.state.transform}px,0,0)` }), onMouseMove: this.handleMouseMove, onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, onMouseLeave: this.handleMouseUp, onTouchStart: this.handleTouchStart, onTouchMove: this.handleTouchMove, onTouchEnd: this.handleTouchEnd }, React.Children.toArray(children).map((child, index) => (React.createElement("li", { key: index, style: { | ||
: "none", overflow: shouldRenderOnSSR ? "hidden" : "unset", transform: `translate3d(${this.state.transform}px,0,0)` }), onMouseMove: this.handleMove, onMouseDown: this.handleDown, onMouseUp: this.handleOut, onMouseEnter: this.handleEnter, onMouseLeave: this.handleOut, onTouchStart: this.handleDown, onTouchMove: this.handleMove, onTouchEnd: this.handleOut }, React.Children.toArray(children).map((child, index) => (React.createElement("li", { key: index, style: { | ||
flex: shouldRenderOnSSR ? `1 0 ${flexBisis}%` : "auto", | ||
width: domFullLoaded ? `${itemWidth}px` : "auto" | ||
width: domFullyLoaded ? `${itemWidth}px` : "auto" | ||
}, className: itemClassName }, child)))), | ||
@@ -351,3 +324,3 @@ shouldShowArrows && !disableLeftArrow && this.renderLeftArrow(), | ||
} | ||
Container.defaultProps = { | ||
Carousel.defaultProps = { | ||
slidesToSlide: 1, | ||
@@ -358,9 +331,6 @@ infinite: false, | ||
itemClassName: "", | ||
keyBoardControl: true | ||
keyBoardControl: true, | ||
autoPlaySpeed: 3000 | ||
}; | ||
const Carousel = (_a) => { | ||
var { children } = _a, rest = __rest(_a, ["children"]); | ||
return (React.createElement(Container, Object.assign({}, rest), children)); | ||
}; | ||
exports.default = Carousel; | ||
//# sourceMappingURL=Carousel.js.map |
@@ -28,2 +28,4 @@ /// <reference types="react" /> | ||
keyBoardControl?: boolean; | ||
autoPlay?: boolean; | ||
autoPlaySpeed?: number; | ||
customTransition?: string; | ||
@@ -30,0 +32,0 @@ transitionDuration?: number; |
{ | ||
"name": "react-multi-carousel", | ||
"version": "1.0.33", | ||
"version": "1.0.34", | ||
"description": "", | ||
@@ -10,2 +10,3 @@ "main": "index.js", | ||
"test": "jest", | ||
"test:watch": "jest --watch", | ||
"storybook": "start-storybook -p 6006", | ||
@@ -31,2 +32,4 @@ "export": "build-storybook -c .storybook -o .out", | ||
"jest": { | ||
"testEnvironment": "jsdom", | ||
"verbose": true, | ||
"testURL": "http://localhost", | ||
@@ -33,0 +36,0 @@ "collectCoverage": true, |
# react-multi-carousel | ||
React carousel component supports multiple items and SSR with typescript. | ||
Lightweight React carousel component supports multiple items and SSR(Server-side rendering) with typescript. | ||
@@ -9,2 +9,7 @@ ## NPM | ||
## Bundle size | ||
[Bundle-size](https://bundlephobia.com/result?p=react-multi-carousel@1.0.33). | ||
2.5kB | ||
## Install | ||
@@ -38,3 +43,17 @@ | ||
## Features. | ||
* Server-side rendering | ||
* Infinite mode | ||
* Custom animation | ||
* AutoPlay mode | ||
* Responsive | ||
* Swipe to slide | ||
* Mouse drag to slide | ||
* Keyboard control to slide | ||
* Multiple items | ||
* Show / hide arrows | ||
* Custom arrows / control buttons | ||
* Custom styling | ||
## Examples | ||
@@ -64,3 +83,8 @@ | ||
infinite={true} | ||
className='test' | ||
autoPlay={this.props.deviceType !== 'mobile' ? true : false} | ||
autoPlaySpeed={1000} | ||
keyBoardControl={true} | ||
customTransition='all .5' | ||
transitionDuration={500} | ||
containerClassName='container-border-green' | ||
removeArrowOnDeviceType={['tablet', 'mobile']} | ||
@@ -101,2 +125,4 @@ deviceType={this.props.deviceType} | ||
keyBoardControl?: boolean; | ||
autoPlay?: boolean; | ||
autoPlaySpeed?: number; // default 3000ms | ||
customTransition?:string; | ||
@@ -117,1 +143,5 @@ transitionDuration?: number; | ||
| `slidesToSlide` | `number` | `1` | How many slides to slide. | | ||
## Contribute | ||
Submit an issue for feature request or submit a pr. |
Sorry, the diff of this file is not supported yet
39662
0.03%142
25.66%