UNPKG

@code-atlas/react-native-snap-carousel

Version:

Swiper/carousel component for React Native with previews, multiple layouts, parallax images, performant handling of huge numbers of items, and RTL support. Compatible with Android & iOS.

169 lines (151 loc) 5.6 kB
import React, { PureComponent } from 'react'; import { I18nManager, Platform, View } from 'react-native'; import { ViewPropTypes } from 'deprecated-react-native-prop-types'; import PropTypes from 'prop-types'; import PaginationDot from './PaginationDot'; import styles from './Pagination.style'; const IS_IOS = Platform.OS === 'ios'; const IS_RTL = I18nManager.isRTL; export default class Pagination extends PureComponent { static propTypes = { activeDotIndex: PropTypes.number.isRequired, dotsLength: PropTypes.number.isRequired, activeOpacity: PropTypes.number, carouselRef: PropTypes.object, containerStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, dotColor: PropTypes.string, dotContainerStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, dotElement: PropTypes.element, dotStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, inactiveDotColor: PropTypes.string, inactiveDotElement: PropTypes.element, inactiveDotOpacity: PropTypes.number, inactiveDotScale: PropTypes.number, inactiveDotStyle: ViewPropTypes ? ViewPropTypes.style : View.propTypes.style, renderDots: PropTypes.func, tappableDots: PropTypes.bool, vertical: PropTypes.bool, accessibilityLabel: PropTypes.string, animatedDuration: PropTypes.number, animatedFriction: PropTypes.number, animatedTension: PropTypes.number, delayPressInDot: PropTypes.number, }; static defaultProps = { inactiveDotOpacity: 0.5, inactiveDotScale: 0.5, tappableDots: false, vertical: false, animatedDuration: 250, animatedFriction: 4, animatedTension: 50, delayPressInDot: 0, } constructor (props) { super(props); // Warnings if ((props.dotColor && !props.inactiveDotColor) || (!props.dotColor && props.inactiveDotColor)) { console.warn( 'react-native-snap-carousel | Pagination: ' + 'You need to specify both `dotColor` and `inactiveDotColor`' ); } if ((props.dotElement && !props.inactiveDotElement) || (!props.dotElement && props.inactiveDotElement)) { console.warn( 'react-native-snap-carousel | Pagination: ' + 'You need to specify both `dotElement` and `inactiveDotElement`' ); } if (props.tappableDots && props.carouselRef === undefined) { console.warn( 'react-native-snap-carousel | Pagination: ' + 'You must specify prop `carouselRef` when setting `tappableDots` to `true`' ); } } _needsRTLAdaptations () { const { vertical } = this.props; return IS_RTL && !IS_IOS && !vertical; } get _activeDotIndex () { const { activeDotIndex, dotsLength } = this.props; return this._needsRTLAdaptations() ? dotsLength - activeDotIndex - 1 : activeDotIndex; } get dots () { const { activeOpacity, carouselRef, dotsLength, dotColor, dotContainerStyle, dotElement, dotStyle, inactiveDotColor, inactiveDotElement, inactiveDotOpacity, inactiveDotScale, inactiveDotStyle, renderDots, tappableDots, animatedDuration, animatedFriction, animatedTension, delayPressInDot, } = this.props; if (renderDots) { return renderDots(this._activeDotIndex, dotsLength, this); } const DefaultDot = <PaginationDot carouselRef={carouselRef} tappable={tappableDots && typeof carouselRef !== 'undefined'} activeOpacity={activeOpacity} color={dotColor} containerStyle={dotContainerStyle} style={dotStyle} inactiveColor={inactiveDotColor} inactiveOpacity={inactiveDotOpacity} inactiveScale={inactiveDotScale} inactiveStyle={inactiveDotStyle} animatedDuration={animatedDuration} animatedFriction={animatedFriction} animatedTension={animatedTension} delayPressInDot={delayPressInDot} />; const dots = [...Array(dotsLength).keys()].map(i => { const isActive = i === this._activeDotIndex; return React.cloneElement( (isActive ? dotElement : inactiveDotElement) || DefaultDot, { key: `pagination-dot-${i}`, active: isActive, index: i } ); }); return dots; } render () { const { dotsLength, containerStyle, vertical, accessibilityLabel } = this.props; if (!dotsLength || dotsLength < 2) { return false; } const style = [ styles.sliderPagination, { flexDirection: vertical ? 'column' : (this._needsRTLAdaptations() ? 'row-reverse' : 'row') }, containerStyle || {} ]; return ( <View pointerEvents={'box-none'} style={style} accessible={!!accessibilityLabel} accessibilityLabel={accessibilityLabel} > { this.dots } </View> ); } }