UNPKG

rmc-tabs

Version:

React Mobile Tabs Component(web & react-native)

227 lines (215 loc) 11.4 kB
import _extends from 'babel-runtime/helpers/extends'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _createClass from 'babel-runtime/helpers/createClass'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; import React from 'react'; import { Animated, Dimensions, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import defaultStyles from './Styles.native'; var WINDOW_WIDTH = Dimensions.get('window').width; export var DefaultTabBar = function (_React$PureComponent) { _inherits(DefaultTabBar, _React$PureComponent); function DefaultTabBar(props) { _classCallCheck(this, DefaultTabBar); var _this = _possibleConstructorReturn(this, (DefaultTabBar.__proto__ || Object.getPrototypeOf(DefaultTabBar)).call(this, props)); _this._tabsMeasurements = []; _this.updateView = function (offset) { var position = Math.floor(offset.value); var pageOffset = offset.value % 1; var tabCount = _this.props.tabs.length; var lastTabPosition = tabCount - 1; if (tabCount === 0 || offset.value < 0 || offset.value > lastTabPosition) { return; } if (_this.necessarilyMeasurementsCompleted(position, position === lastTabPosition)) { _this.updateTabPanel(position, pageOffset); _this.updateTabUnderline(position, pageOffset, tabCount); } }; _this.onPress = function (index) { var _this$props = _this.props, goToTab = _this$props.goToTab, onTabClick = _this$props.onTabClick, tabs = _this$props.tabs; onTabClick && onTabClick(tabs[index], index); goToTab && goToTab(index); }; _this.measureTab = function (page, event) { var _event$nativeEvent$la = event.nativeEvent.layout, x = _event$nativeEvent$la.x, width = _event$nativeEvent$la.width, height = _event$nativeEvent$la.height; _this._tabsMeasurements[page] = { left: x, right: x + width, width: width, height: height }; _this.updateView({ value: _this.props.scrollValue._value }); }; _this.onTabContainerLayout = function (e) { _this._tabContainerMeasurements = e.nativeEvent.layout; var width = _this._tabContainerMeasurements.width; if (width < WINDOW_WIDTH) { width = WINDOW_WIDTH; } _this.setState({ _tabContainerWidth: width }); if (!_this.props.dynamicTabUnderlineWidth) { _this.state._widthTabUnderline.setValue(width / _this.props.tabs.length); } _this.updateView({ value: _this.props.scrollValue._value }); }; _this.onContainerLayout = function (e) { _this._containerMeasurements = e.nativeEvent.layout; _this.setState({ _containerWidth: _this._containerMeasurements.width }); _this.updateView({ value: _this.props.scrollValue._value }); }; _this.state = { _leftTabUnderline: new Animated.Value(0), _widthTabUnderline: new Animated.Value(0), _containerWidth: WINDOW_WIDTH, _tabContainerWidth: WINDOW_WIDTH }; return _this; } _createClass(DefaultTabBar, [{ key: 'componentDidMount', value: function componentDidMount() { this.props.scrollValue.addListener(this.updateView); } }, { key: 'necessarilyMeasurementsCompleted', value: function necessarilyMeasurementsCompleted(position, isLastTab) { return this._tabsMeasurements[position] && (isLastTab || this._tabsMeasurements[position + 1]) && this._tabContainerMeasurements && this._containerMeasurements; } }, { key: 'updateTabPanel', value: function updateTabPanel(position, pageOffset) { var containerWidth = this._containerMeasurements.width; var tabWidth = this._tabsMeasurements[position].width; var nextTabMeasurements = this._tabsMeasurements[position + 1]; var nextTabWidth = nextTabMeasurements && nextTabMeasurements.width || 0; var tabOffset = this._tabsMeasurements[position].left; var absolutePageOffset = pageOffset * tabWidth; var newScrollX = tabOffset + absolutePageOffset; newScrollX -= (containerWidth - (1 - pageOffset) * tabWidth - pageOffset * nextTabWidth) / 2; newScrollX = newScrollX >= 0 ? newScrollX : 0; if (Platform.OS === 'android') { this._scrollView.scrollTo({ x: newScrollX, y: 0, animated: false }); } else { var rightBoundScroll = this._tabContainerMeasurements.width - this._containerMeasurements.width; newScrollX = newScrollX > rightBoundScroll ? rightBoundScroll : newScrollX; this._scrollView.scrollTo({ x: newScrollX, y: 0, animated: false }); } } }, { key: 'updateTabUnderline', value: function updateTabUnderline(position, pageOffset, tabCount) { var dynamicTabUnderlineWidth = this.props.dynamicTabUnderlineWidth; if (0 <= position && position <= tabCount - 1) { if (dynamicTabUnderlineWidth) { var nowLeft = this._tabsMeasurements[position].left; var nowRight = this._tabsMeasurements[position].right; var nextTabLeft = this._tabsMeasurements[position + 1].left; var nextTabRight = this._tabsMeasurements[position + 1].right; var newLineLeft = pageOffset * nextTabLeft + (1 - pageOffset) * nowLeft; var newLineRight = pageOffset * nextTabRight + (1 - pageOffset) * nowRight; this.state._leftTabUnderline.setValue(newLineLeft); this.state._widthTabUnderline.setValue(newLineRight - newLineLeft); } else { var _nowLeft = position * this.state._tabContainerWidth / tabCount; var _nextTabLeft = (position + 1) * this.state._tabContainerWidth / tabCount; var _newLineLeft = pageOffset * _nextTabLeft + (1 - pageOffset) * _nowLeft; this.state._leftTabUnderline.setValue(_newLineLeft); } } } }, { key: 'renderTab', value: function renderTab(tab, index, width, onLayoutHandler) { var _this2 = this; var _props = this.props, activeTextColor = _props.tabBarActiveTextColor, inactiveTextColor = _props.tabBarInactiveTextColor, textStyle = _props.tabBarTextStyle, activeTab = _props.activeTab, renderTab = _props.renderTab, _props$styles = _props.styles, styles = _props$styles === undefined ? defaultStyles : _props$styles; var isTabActive = activeTab === index; var textColor = isTabActive ? activeTextColor || styles.TabBar.activeTextColor : inactiveTextColor || styles.TabBar.inactiveTextColor; return React.createElement( TouchableOpacity, { activeOpacity: 1, key: tab.title + '_' + index, accessible: true, accessibilityTraits: 'button', onPress: function onPress() { return _this2.onPress(index); }, onLayout: onLayoutHandler }, React.createElement( View, { style: _extends({}, styles.TabBar.tab, this.props.tabStyle, { width: width }) }, renderTab ? renderTab(tab) : React.createElement( Text, { style: _extends({ color: textColor }, styles.TabBar.textStyle, textStyle) }, tab.title ) ) ); } }, { key: 'render', value: function render() { var _this3 = this; var _props2 = this.props, tabs = _props2.tabs, _props2$page = _props2.page, page = _props2$page === undefined ? 1 : _props2$page, tabBarUnderlineStyle = _props2.tabBarUnderlineStyle, tabBarBackgroundColor = _props2.tabBarBackgroundColor, _props2$styles = _props2.styles, styles = _props2$styles === undefined ? defaultStyles : _props2$styles, tabsContainerStyle = _props2.tabsContainerStyle, renderUnderline = _props2.renderUnderline, keyboardShouldPersistTaps = _props2.keyboardShouldPersistTaps; var tabUnderlineStyle = _extends({ position: 'absolute', bottom: 0 }, styles.TabBar.underline, tabBarUnderlineStyle); var dynamicTabUnderline = { left: this.state._leftTabUnderline, width: this.state._widthTabUnderline }; var tabWidth = this.state._containerWidth / Math.min(page, tabs.length); var underlineProps = { style: _extends({}, tabUnderlineStyle, dynamicTabUnderline) }; return React.createElement( View, { style: _extends({}, styles.TabBar.container, { backgroundColor: tabBarBackgroundColor }), onLayout: this.onContainerLayout }, React.createElement( ScrollView, { ref: function ref(scrollView) { _this3._scrollView = scrollView; }, horizontal: true, showsHorizontalScrollIndicator: false, showsVerticalScrollIndicator: false, directionalLockEnabled: true, bounces: false, scrollsToTop: false, scrollEnabled: tabs.length > page, keyboardShouldPersistTaps: keyboardShouldPersistTaps }, React.createElement( View, { style: _extends({}, styles.TabBar.tabs, tabsContainerStyle, { backgroundColor: tabBarBackgroundColor }), onLayout: this.onTabContainerLayout }, tabs.map(function (name, index) { var tab = { title: name }; if (tabs.length - 1 >= index) { tab = tabs[index]; } return _this3.renderTab(tab, index, tabWidth, _this3.measureTab.bind(_this3, index)); }), renderUnderline ? renderUnderline(underlineProps) : React.createElement(Animated.View, underlineProps) ) ) ); } }]); return DefaultTabBar; }(React.PureComponent); DefaultTabBar.defaultProps = { animated: true, tabs: [], goToTab: function goToTab() {}, activeTab: 0, page: 5, tabBarUnderlineStyle: {}, tabBarBackgroundColor: '#fff', tabBarActiveTextColor: '', tabBarInactiveTextColor: '', tabBarTextStyle: {}, dynamicTabUnderlineWidth: false, styles: defaultStyles };