import React, { PureComponent } from 'react'; import { I18nManager, Platform, View, StyleProp, ViewStyle } from 'react-native'; import PropTypes from 'prop-types'; import PaginationDot from './PaginationDot'; import styles from './Pagination.style'; import Carousel from '../carousel/Carousel'; const IS_IOS = Platform.OS === 'ios'; const IS_RTL = I18nManager.isRTL; type PaginationAllProps = { activeDotIndex: number, dotsLength: number, activeOpacity?: number, carouselRef: React.RefObject>, containerStyle: StyleProp, dotColor: string, dotContainerStyle: StyleProp, dotElement: JSX.Element, dotStyle: StyleProp, inactiveDotColor: string, inactiveDotElement: JSX.Element, inactiveDotOpacity: number, inactiveDotScale: number, inactiveDotStyle: StyleProp, renderDots: (activeDotIndex: number, dotsLength: number, pagination: Pagination) => JSX.Element, tappableDots: boolean, vertical: boolean, accessibilityLabel: string, animatedDuration: number, animatedFriction: number, animatedTension: number, delayPressInDot: number } type PaginationProps = Omit & Partial>; export default class Pagination extends PureComponent { static defaultProps = { inactiveDotOpacity: 0.5, inactiveDotScale: 0.5, tappableDots: false, vertical: false, animatedDuration: 250, animatedFriction: 4, animatedTension: 50, delayPressInDot: 0, } as const constructor(props: PaginationAllProps) { 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 = 0, carouselRef, dotsLength, dotColor, dotContainerStyle, dotElement, dotStyle, inactiveDotColor, inactiveDotElement, inactiveDotOpacity, inactiveDotScale, inactiveDotStyle, renderDots, tappableDots, animatedDuration, animatedFriction, animatedTension, delayPressInDot, } = this.props as PaginationAllProps; if (renderDots) { return renderDots(this._activeDotIndex, dotsLength, this); } const DefaultDot = ; 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 ] as StyleProp; return ( {this.dots} ); } }