diff --git a/lib/index.js b/lib/index.js
index f125bdc6..56c23225 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,6 +1,6 @@
-import React, {Component} from 'react'
-import ReactNative from 'react-native'
-import PropTypes from 'prop-types'
+import React, { Component } from "react";
+import ReactNative from "react-native";
+import PropTypes from "prop-types";
const {
ViewPropTypes,
@@ -11,13 +11,13 @@ const {
StyleSheet,
InteractionManager,
Platform,
- RefreshControl
-} = ReactNative
+ RefreshControl,
+} = ReactNative;
// import TimerMixin from 'react-timer-mixin'
-import SceneComponent from './SceneComponent'
-import DefaultTabBar from './DefaultTabBar'
-import ScrollableTabBar from './ScrollableTabBar'
+import SceneComponent from "./SceneComponent";
+import DefaultTabBar from "./DefaultTabBar";
+import ScrollableTabBar from "./ScrollableTabBar";
/**
* pullToRefresh: function used to trigger pull to refresh action.
@@ -27,21 +27,23 @@ import ScrollableTabBar from './ScrollableTabBar'
class ScrollableTabView extends Component {
constructor(props) {
- super(props)
- this.state = this.getInitialState()
- this._handleLayout = this._handleLayout.bind(this)
- this.goToPage = this.goToPage.bind(this)
- this.renderTabBar = this.renderTabBar.bind(this)
- this.updateSceneKeys = this.updateSceneKeys.bind(this)
- this.newSceneKeys = this.newSceneKeys.bind(this)
- this._shouldRenderSceneKey = this._shouldRenderSceneKey.bind(this)
- this._keyExists = this._keyExists.bind(this)
- this._makeSceneKey = this._makeSceneKey.bind(this)
- this.renderScrollableContent = this.renderScrollableContent.bind(this)
- this._composeScenes = this._composeScenes.bind(this)
- this._onMomentumScrollBeginAndEnd = this._onMomentumScrollBeginAndEnd.bind(this)
- this._updateSelectedPage = this._updateSelectedPage.bind(this)
- this.renderCollapsableBar = this.renderCollapsableBar.bind(this)
+ super(props);
+ this.state = this.getInitialState();
+ this._handleLayout = this._handleLayout.bind(this);
+ this.goToPage = this.goToPage.bind(this);
+ this.renderTabBar = this.renderTabBar.bind(this);
+ this.updateSceneKeys = this.updateSceneKeys.bind(this);
+ this.newSceneKeys = this.newSceneKeys.bind(this);
+ this._shouldRenderSceneKey = this._shouldRenderSceneKey.bind(this);
+ this._keyExists = this._keyExists.bind(this);
+ this._makeSceneKey = this._makeSceneKey.bind(this);
+ this.renderScrollableContent = this.renderScrollableContent.bind(this);
+ this._composeScenes = this._composeScenes.bind(this);
+ this._onMomentumScrollBeginAndEnd = this._onMomentumScrollBeginAndEnd.bind(
+ this
+ );
+ this._updateSelectedPage = this._updateSelectedPage.bind(this);
+ this.renderCollapsableBar = this.renderCollapsableBar.bind(this);
}
// mixins = [TimerMixin]
@@ -63,304 +65,368 @@ class ScrollableTabView extends Component {
}*/
getInitialState() {
- const width = Dimensions.get('window').width
+ const width = Dimensions.get("window").width;
return {
currentPage: this.props.initialPage,
scrollX: new Animated.Value(this.props.initialPage * width),
scrollValue: new Animated.Value(this.props.initialPage),
containerWidth: width,
- sceneKeys: this.newSceneKeys({currentPage: this.props.initialPage}),
- refreshing: false
- }
+ sceneKeys: this.newSceneKeys({ currentPage: this.props.initialPage }),
+ refreshing: false,
+ };
}
_onRefresh = () => {
//if there is not pullToRefresh function do nothing
- if (!this.props.pullToRefresh)
- return
+ if (!this.props.pullToRefresh) return;
- this.setState({refreshing: true})
- this.props.pullToRefresh(response => {
- this.setState({refreshing: false})
- })
- }
+ this.setState({ refreshing: true });
+ this.props.pullToRefresh((response) => {
+ this.setState({ refreshing: false });
+ });
+ };
componentDidMount() {
setTimeout(() => {
InteractionManager.runAfterInteractions(() => {
- if (Platform.OS === 'android') {
- this.goToPage(this.props.initialPage, false)
+ if (Platform.OS === "android") {
+ this.goToPage(this.props.initialPage, false);
}
- })
- }, 0)
-
- this.state.scrollX.addListener(({value}) => {
- const scrollValue = value / this.state.containerWidth
- this.state.scrollValue.setValue(scrollValue)
- this.props.onScroll(scrollValue)
- })
+ });
+ }, 0);
+
+ this.state.scrollX.addListener(({ value }) => {
+ const scrollValue = value / this.state.containerWidth;
+ this.state.scrollValue.setValue(scrollValue);
+ this.props.onScroll(scrollValue);
+ });
}
componentWillReceiveProps(props) {
if (props.children !== this.props.children) {
- this.updateSceneKeys({page: this.state.currentPage, children: props.children})
+ this.updateSceneKeys({
+ page: this.state.currentPage,
+ children: props.children,
+ });
}
if (props.page >= 0 && props.page !== this.state.currentPage) {
- this.goToPage(props.page)
+ this.goToPage(props.page);
}
}
goToPage(pageNumber, animated = !this.props.scrollWithoutAnimation) {
- const offset = pageNumber * this.state.containerWidth
- if (this.scrollView && this.scrollView._component && this.scrollView._component.scrollTo) {
- this.scrollView._component.scrollTo({x: offset, y: 0, animated})
+ const offset = pageNumber * this.state.containerWidth;
+ if (this.scrollView && this.scrollView.scrollTo) {
+ this.scrollView.scrollTo({ x: offset, y: 0, animated });
}
- const currentPage = this.state.currentPage
+ const currentPage = this.state.currentPage;
this.updateSceneKeys({
page: pageNumber,
- callback: this._onChangeTab.bind(this, currentPage, pageNumber)
- })
+ callback: this._onChangeTab.bind(this, currentPage, pageNumber),
+ });
}
renderTabBar(props) {
if (this.props.renderTabBar === false) {
- return null
+ return null;
} else if (this.props.renderTabBar) {
- return React.cloneElement(this.props.renderTabBar(props), props)
+ return React.cloneElement(this.props.renderTabBar(props), props);
} else {
- return
+ return ;
}
}
updateSceneKeys({
- page, children = this.props.children, callback = () => {
- }
- }) {
- let newKeys = this.newSceneKeys({previousKeys: this.state.sceneKeys, currentPage: page, children})
- this.setState({currentPage: page, sceneKeys: newKeys}, callback)
+ page,
+ children = this.props.children,
+ callback = () => {},
+ }) {
+ let newKeys = this.newSceneKeys({
+ previousKeys: this.state.sceneKeys,
+ currentPage: page,
+ children,
+ });
+ this.setState({ currentPage: page, sceneKeys: newKeys }, callback);
}
- newSceneKeys({previousKeys = [], currentPage = 0, children = this.props.children}) {
- let newKeys = []
+ newSceneKeys({
+ previousKeys = [],
+ currentPage = 0,
+ children = this.props.children,
+ }) {
+ let newKeys = [];
this._children(children).forEach((child, idx) => {
- let key = this._makeSceneKey(child, idx)
- if (this._keyExists(previousKeys, key) ||
- this._shouldRenderSceneKey(idx, currentPage)) {
- newKeys.push(key)
+ let key = this._makeSceneKey(child, idx);
+ if (
+ this._keyExists(previousKeys, key) ||
+ this._shouldRenderSceneKey(idx, currentPage)
+ ) {
+ newKeys.push(key);
}
- })
- return newKeys
+ });
+ return newKeys;
}
_shouldRenderSceneKey(idx, currentPageKey) {
- let numOfSibling = this.props.prerenderingSiblingsNumber
- return (idx < (currentPageKey + numOfSibling + 1) &&
- idx > (currentPageKey - numOfSibling - 1))
+ let numOfSibling = this.props.prerenderingSiblingsNumber;
+ return (
+ idx < currentPageKey + numOfSibling + 1 &&
+ idx > currentPageKey - numOfSibling - 1
+ );
}
_keyExists(sceneKeys, key) {
- return sceneKeys.find((sceneKey) => key === sceneKey)
+ return sceneKeys.find((sceneKey) => key === sceneKey);
}
_makeSceneKey(child, idx) {
- return child.props.tabLabel + '_' + idx
+ return child.props.tabLabel + "_" + idx;
}
renderScrollableContent() {
//in case of the collapsible scroll view the pull to refresh animation will be applied on the container
//on the other case the refresh animations will be applied here.
- const isContainerScrollView = !!this.props.collapsableBar
-
- const scenes = this._composeScenes()
- return || undefined}
- showsVerticalScrollIndicator={this.props.showsVerticalScrollIndicator}
- showsHorizontalScrollIndicator={this.props.showsHorizontalScrollIndicator}
- horizontal
- pagingEnabled
- automaticallyAdjustContentInsets={false}
- contentOffset={{x: this.props.initialPage * this.state.containerWidth}}
- ref={scrollView => this.scrollView = scrollView}
- onScroll={Animated.event([{nativeEvent: {contentOffset: {x: this.state.scrollX}}}], {useNativeDriver: true})}
- onMomentumScrollBegin={this._onMomentumScrollBeginAndEnd}
- onMomentumScrollEnd={this._onMomentumScrollBeginAndEnd}
- scrollEventThrottle={16}
- scrollsToTop={false}
- scrollEnabled={!this.props.locked}
- directionalLockEnabled
- alwaysBounceVertical={false}
- keyboardDismissMode="on-drag"
- {...this.props.contentProps}
- >
- {scenes}
-
+ const isContainerScrollView = !!this.props.collapsableBar;
+
+ const scenes = this._composeScenes();
+ return (
+
+ )) ||
+ undefined
+ }
+ showsVerticalScrollIndicator={this.props.showsVerticalScrollIndicator}
+ showsHorizontalScrollIndicator={
+ this.props.showsHorizontalScrollIndicator
+ }
+ horizontal
+ pagingEnabled
+ automaticallyAdjustContentInsets={false}
+ contentOffset={{
+ x: this.props.initialPage * this.state.containerWidth,
+ }}
+ ref={(scrollView) => (this.scrollView = scrollView)}
+ onScroll={Animated.event(
+ [{ nativeEvent: { contentOffset: { x: this.state.scrollX } } }],
+ { useNativeDriver: true }
+ )}
+ onMomentumScrollBegin={this._onMomentumScrollBeginAndEnd}
+ onMomentumScrollEnd={this._onMomentumScrollBeginAndEnd}
+ scrollEventThrottle={16}
+ scrollsToTop={false}
+ scrollEnabled={!this.props.locked}
+ directionalLockEnabled
+ alwaysBounceVertical={false}
+ keyboardDismissMode="on-drag"
+ {...this.props.contentProps}
+ >
+ {scenes}
+
+ );
}
_composeScenes() {
return this._children().map((child, idx) => {
- let key = this._makeSceneKey(child, idx)
- let element
+ let key = this._makeSceneKey(child, idx);
+ let element;
if (!!this.props.collapsableBar) {
- element = this.state.currentPage === idx ? child : null
+ element = this.state.currentPage === idx ? child : null;
} else {
- element = this._keyExists(this.state.sceneKeys, key) ? child :
+ element = this._keyExists(this.state.sceneKeys, key) ? (
+ child
+ ) : (
+
+ );
}
- return
- {element}
-
- })
+ return (
+
+ {element}
+
+ );
+ });
}
_onMomentumScrollBeginAndEnd(e) {
- const offsetX = e.nativeEvent.contentOffset.x
- const page = Math.round(offsetX / this.state.containerWidth)
+ const offsetX = e.nativeEvent.contentOffset.x;
+ const page = Math.round(offsetX / this.state.containerWidth);
if (this.state.currentPage !== page) {
- this._updateSelectedPage(page)
+ this._updateSelectedPage(page);
}
}
_updateSelectedPage(nextPage) {
- let localNextPage = nextPage
- if (typeof localNextPage === 'object') {
- localNextPage = nextPage.nativeEvent.position
+ let localNextPage = nextPage;
+ if (typeof localNextPage === "object") {
+ localNextPage = nextPage.nativeEvent.position;
}
- const currentPage = this.state.currentPage
+ const currentPage = this.state.currentPage;
this.updateSceneKeys({
page: localNextPage,
- callback: this._onChangeTab.bind(this, currentPage, localNextPage)
- })
+ callback: this._onChangeTab.bind(this, currentPage, localNextPage),
+ });
}
_onChangeTab(prevPage, currentPage) {
this.props.onChangeTab({
i: currentPage,
ref: this._children()[currentPage],
- from: prevPage
- })
+ from: prevPage,
+ });
if (this.contentScrollDistance >= this.collapsableBarHeight) {
- this.contentView.scrollTo({x: 0, y: this.collapsableBarHeight, animated: false})
+ this.contentView.scrollTo({
+ x: 0,
+ y: this.collapsableBarHeight,
+ animated: false,
+ });
}
}
_handleLayout(e) {
- const {width} = e.nativeEvent.layout
+ const { width } = e.nativeEvent.layout;
if (Math.round(width) !== Math.round(this.state.containerWidth)) {
- this.setState({containerWidth: width})
+ this.setState({ containerWidth: width });
requestAnimationFrame(() => {
- this.goToPage(this.state.currentPage)
- })
+ this.goToPage(this.state.currentPage);
+ });
}
}
_children(children = this.props.children) {
- return React.Children.map(children, (child) => child)
+ return React.Children.map(children, (child) => child);
}
renderCollapsableBar() {
if (!this.props.collapsableBar) {
- return null
+ return null;
}
return React.cloneElement(this.props.collapsableBar, {
- onLayout: event => {
- this.collapsableBarHeight = event.nativeEvent.layout.height
- }
- })
+ onLayout: (event) => {
+ this.collapsableBarHeight = event.nativeEvent.layout.height;
+ },
+ });
}
render() {
- let overlayTabs = (this.props.tabBarPosition === 'overlayTop' || this.props.tabBarPosition === 'overlayBottom')
+ let overlayTabs =
+ this.props.tabBarPosition === "overlayTop" ||
+ this.props.tabBarPosition === "overlayBottom";
let tabBarProps = {
goToPage: this.goToPage,
tabs: this._children().map((child) => child.props.tabLabel),
activeTab: this.state.currentPage,
scrollX: this.state.scrollX,
scrollValue: this.state.scrollValue,
- containerWidth: this.state.containerWidth
- }
+ containerWidth: this.state.containerWidth,
+ };
if (this.props.tabBarBackgroundColor) {
- tabBarProps.backgroundColor = this.props.tabBarBackgroundColor
+ tabBarProps.backgroundColor = this.props.tabBarBackgroundColor;
}
if (this.props.tabBarActiveTextColor) {
- tabBarProps.activeTextColor = this.props.tabBarActiveTextColor
+ tabBarProps.activeTextColor = this.props.tabBarActiveTextColor;
}
if (this.props.tabBarInactiveTextColor) {
- tabBarProps.inactiveTextColor = this.props.tabBarInactiveTextColor
+ tabBarProps.inactiveTextColor = this.props.tabBarInactiveTextColor;
}
if (this.props.tabBarTextStyle) {
- tabBarProps.textStyle = this.props.tabBarTextStyle
+ tabBarProps.textStyle = this.props.tabBarTextStyle;
}
if (this.props.tabBarUnderlineStyle) {
- tabBarProps.underlineStyle = this.props.tabBarUnderlineStyle
+ tabBarProps.underlineStyle = this.props.tabBarUnderlineStyle;
}
if (overlayTabs) {
tabBarProps.style = {
- position: 'absolute',
+ position: "absolute",
left: 0,
right: 0,
- [this.props.tabBarPosition === 'overlayTop' ? 'top' : 'bottom']: 0
- }
+ [this.props.tabBarPosition === "overlayTop" ? "top" : "bottom"]: 0,
+ };
}
- const ContainerView = this.props.collapsableBar ? ScrollView : View
- const isScrollView = this.props.collapsableBar ? true : false
-
- return ( || undefined}
- showsVerticalScrollIndicator={isScrollView && this.props.showsVerticalScrollIndicator}
- showsHorizontalScrollIndicator={isScrollView && this.props.showsHorizontalScrollIndicator}
+ const ContainerView = this.props.collapsableBar ? ScrollView : View;
+ const isScrollView = this.props.collapsableBar ? true : false;
+
+ return (
+
+ )) ||
+ undefined
+ }
+ showsVerticalScrollIndicator={
+ isScrollView && this.props.showsVerticalScrollIndicator
+ }
+ showsHorizontalScrollIndicator={
+ isScrollView && this.props.showsHorizontalScrollIndicator
+ }
style={[styles.container, this.props.style]}
onLayout={this._handleLayout} //()=>
- ref={contentView => this.contentView = contentView}
- onMomentumScrollEnd={event => {
- this.contentScrollDistance = event.nativeEvent.contentOffset.y
+ ref={(contentView) => (this.contentView = contentView)}
+ onMomentumScrollEnd={(event) => {
+ this.contentScrollDistance = event.nativeEvent.contentOffset.y;
}}
- stickyHeaderIndices={this.props.collapsableBar ? [1] : []}>
-
+ stickyHeaderIndices={this.props.collapsableBar ? [1] : []}
+ >
+
{this.renderCollapsableBar()}
- {this.props.tabBarPosition === 'top' && this.renderTabBar(tabBarProps)}
+ {this.props.tabBarPosition === "top" &&
+ this.renderTabBar(tabBarProps)}
{this.renderScrollableContent()}
- {(this.props.tabBarPosition === 'bottom' || overlayTabs) && this.renderTabBar(tabBarProps)}
+ {(this.props.tabBarPosition === "bottom" || overlayTabs) &&
+ this.renderTabBar(tabBarProps)}
- )
+ );
}
}
ScrollableTabView.defaultProps = {
- tabBarPosition: 'top',
+ tabBarPosition: "top",
initialPage: 0,
page: -1,
- onChangeTab: () => {
- },
- onScroll: () => {
- },
+ onChangeTab: () => {},
+ onScroll: () => {},
contentProps: {},
scrollWithoutAnimation: false,
locked: false,
- prerenderingSiblingsNumber: 0
-}
+ prerenderingSiblingsNumber: 0,
+};
ScrollableTabView.propTypes = {
- tabBarPosition: PropTypes.oneOf(['top', 'bottom', 'overlayTop', 'overlayBottom']),
+ tabBarPosition: PropTypes.oneOf([
+ "top",
+ "bottom",
+ "overlayTop",
+ "overlayBottom",
+ ]),
initialPage: PropTypes.number,
page: PropTypes.number,
onChangeTab: PropTypes.func,
@@ -371,20 +437,20 @@ ScrollableTabView.propTypes = {
scrollWithoutAnimation: PropTypes.bool,
locked: PropTypes.bool,
prerenderingSiblingsNumber: PropTypes.number,
- collapsableBar: PropTypes.node
-}
+ collapsableBar: PropTypes.node,
+};
const styles = StyleSheet.create({
container: {
- flex: 1
+ flex: 1,
},
scrollableContentAndroid: {
- flex: 1
- }
-})
+ flex: 1,
+ },
+});
module.exports = {
DefaultTabBar,
ScrollableTabBar,
- ScrollableTabView
-}
+ ScrollableTabView,
+};