UNPKG

react-native-ui-lib

Version:

[![Build Status](https://travis-ci.org/wix/react-native-ui-lib.svg?branch=master)](https://travis-ci.org/wix/react-native-ui-lib) [![npm](https://img.shields.io/npm/v/react-native-ui-lib.svg)](https://www.npmjs.com/package/react-native-ui-lib) [![NPM Down

101 lines (100 loc) 3.56 kB
import React from "react"; import { ScrollView, StyleSheet } from "react-native"; import _ from "lodash"; import { BaseComponent } from "../../commons"; import View from "../view"; import { Constants } from "../../helpers"; import * as presenter from "./CarouselPresenter"; const OFFSET_PIXEL_CORRECTION = 5; /** * @description: Carousel for scrolling pages horizontally * @gif: https://media.giphy.com/media/l0HU7f8gjpRlMRhKw/giphy.gif, https://media.giphy.com/media/3oFzmcjX9OhpyckhcQ/giphy.gif * @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/CarouselScreen.js */ export default class Carousel extends BaseComponent { constructor(props) { super(props); this.state = { currentPage: props.initialPage, currentStandingPage: props.initialPage }; this.onScroll = this.onScroll.bind(this); this.updateOffset = this.updateOffset.bind(this); } generateStyles() { this.styles = createStyles(this.props); } get pageWidth() { return Math.floor(this.props.pageWidth); } onScroll(event) { const { loop } = this.props; const offsetX = event.nativeEvent.contentOffset.x; if (offsetX >= 0) { const { currentStandingPage } = this.state; const newPage = presenter.calcPageIndex(offsetX, this.props); this.setState({ currentPage: newPage }); // finished full page scroll if (offsetX % this.pageWidth <= OFFSET_PIXEL_CORRECTION) { this.setState({ currentStandingPage: newPage }); if (currentStandingPage !== newPage) { _.invoke(this.props, "onChangePage", newPage, currentStandingPage); } } } if (loop && presenter.isOutOfBounds(offsetX, this.props)) { this.updateOffset(); } _.invoke(this.props, "onScroll", event); } updateOffset(animated = false) { const x = presenter.calcOffset(this.props, this.state); this.carousel.scrollTo({ x, animated }); } componentDidMount() { setTimeout(() => { this.updateOffset(); }, 0); } cloneChild(child) { if (!child.key) { return child; } return React.cloneElement(child, { key: `${child.key}-clone` }); } renderChildren() { const { children, loop } = this.props; const length = presenter.getChildrenLength(this.props); const childrenArray = React.Children.toArray(children); if (loop) { childrenArray.unshift(this.cloneChild(children[length - 1])); childrenArray.push(this.cloneChild(children[0])); } return childrenArray; } render() { const { containerStyle } = this.props; return (<View flex style={containerStyle}> <ScrollView ref={scrollView => { this.carousel = scrollView; }} horizontal showsHorizontalScrollIndicator={false} pagingEnabled onScroll={this.onScroll} scrollEventThrottle={200}> {this.renderChildren()} </ScrollView> </View>); } goToPage(pageIndex, animated = true) { this.setState({ currentPage: pageIndex }, () => this.updateOffset(animated)); } } Carousel.displayName = "Carousel"; Carousel.defaultProps = { initialPage: 0, pageWidth: Constants.screenWidth }; function createStyles() { return StyleSheet.create({}); }