@ant-design/react-native
Version:
基于蚂蚁金服移动设计规范的 React Native 组件库
361 lines (337 loc) • 15.4 kB
JavaScript
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 ViewPager from '@react-native-community/viewpager';
import React from 'react';
import { Animated, Dimensions } from 'react-native';
import { WithTheme } from '../style';
import View from '../view';
import { DefaultTabBar } from './DefaultTabBar';
import TabsStyles from './style/tabs';
var instanceId = 0;
export var Tabs = function (_React$PureComponent) {
_inherits(Tabs, _React$PureComponent);
function Tabs(props) {
_classCallCheck(this, Tabs);
var _this = _possibleConstructorReturn(this, (Tabs.__proto__ || Object.getPrototypeOf(Tabs)).call(this, props));
_this.tabCache = {};
_this.renderContent = function () {
var getSubElements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this.getSubElements();
var _this$props = _this.props,
tabs = _this$props.tabs,
usePaged = _this$props.usePaged,
destroyInactiveTab = _this$props.destroyInactiveTab;
var _this$state = _this.state,
_this$state$currentTa = _this$state.currentTab,
currentTab = _this$state$currentTa === undefined ? 0 : _this$state$currentTa,
_this$state$container = _this$state.containerWidth,
containerWidth = _this$state$container === undefined ? 0 : _this$state$container;
var content = tabs.map(function (tab, index) {
var key = tab.key || 'tab_' + index;
// update tab cache
if (_this.shouldRenderTab(index)) {
_this.tabCache[index] = _this.getSubElement(tab, index, getSubElements);
} else if (destroyInactiveTab) {
_this.tabCache[index] = undefined;
}
return React.createElement(
View,
{ key: key
// active={currentTab === index}
, style: { width: containerWidth } },
_this.tabCache[index]
);
});
return React.createElement(
ViewPager,
{ key: '$content', keyboardDismissMode: 'on-drag', initialPage: currentTab, scrollEnabled: _this.props.swipeable || usePaged, onPageScroll: function onPageScroll(e) {
_this.state.scrollX.setValue(e.nativeEvent.position * _this.state.containerWidth);
}, style: { flex: 1 }, onPageSelected: function onPageSelected(e) {
var index = e.nativeEvent.position;
_this.setState({
currentTab: index
}, function () {
// tslint:disable-next-line:no-unused-expression
_this.props.onChange && _this.props.onChange(tabs[index], index);
});
_this.nextCurrentTab = index;
}, ref: function ref(_ref) {
return _this.viewPager = _ref;
} },
content
);
};
_this.onMomentumScrollEnd = function (e) {
var offsetX = e.nativeEvent.contentOffset.x;
var page = _this.getOffsetIndex(offsetX, _this.state.containerWidth);
if (_this.state.currentTab !== page) {
_this.goToTab(page);
}
};
_this.handleLayout = function (e) {
var width = e.nativeEvent.layout.width;
requestAnimationFrame(function () {
_this.scrollTo(_this.state.currentTab, false);
});
if (Math.round(width) !== Math.round(_this.state.containerWidth)) {
_this.setState({ containerWidth: width });
}
};
_this.scrollTo = function (index) {
var animated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
if (_this.viewPager) {
if (animated) {
_this.viewPager.setPage(index);
} else {
_this.viewPager.setPageWithoutAnimation(index);
}
return;
}
};
_this.isTabVertical = function () {
var direction = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this.props.tabDirection;
return direction === 'vertical';
};
_this.shouldRenderTab = function (idx) {
var _this$props$prerender = _this.props.prerenderingSiblingsNumber,
prerenderingSiblingsNumber = _this$props$prerender === undefined ? 0 : _this$props$prerender;
var _this$state$currentTa2 = _this.state.currentTab,
currentTab = _this$state$currentTa2 === undefined ? 0 : _this$state$currentTa2;
return currentTab - prerenderingSiblingsNumber <= idx && idx <= currentTab + prerenderingSiblingsNumber;
};
_this.getOffsetIndex = function (current, width) {
var threshold = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _this.props.distanceToChangeTab || 0;
var ratio = Math.abs(current / width);
var direction = ratio > _this.state.currentTab ? '<' : '>';
var index = Math.floor(ratio);
switch (direction) {
case '<':
return ratio - index > threshold ? index + 1 : index;
case '>':
return 1 - ratio + index > threshold ? index : index + 1;
default:
return Math.round(ratio);
}
};
_this.getSubElements = function () {
var children = _this.props.children;
var subElements = {};
return function () {
var defaultPrefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '$i$-';
var allPrefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '$ALL$';
if (Array.isArray(children)) {
children.forEach(function (child, index) {
if (child.key) {
subElements[child.key] = child;
}
subElements['' + defaultPrefix + index] = child;
});
} else if (children) {
subElements[allPrefix] = children;
}
return subElements;
};
};
var width = Dimensions.get('window').width;
var pageIndex = _this.getTabIndex(props);
_this.state = {
currentTab: pageIndex,
scrollX: new Animated.Value(pageIndex * width),
scrollValue: new Animated.Value(pageIndex),
containerWidth: width
};
_this.nextCurrentTab = _this.state.currentTab;
_this.instanceId = instanceId++;
return _this;
}
_createClass(Tabs, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
this.prevCurrentTab = this.state.currentTab;
this.state.scrollX.addListener(function (_ref2) {
var value = _ref2.value;
var scrollValue = value / _this2.state.containerWidth;
_this2.state.scrollValue.setValue(scrollValue);
});
}
}, {
key: 'render',
value: function render() {
var _this3 = this;
var _props = this.props,
tabBarPosition = _props.tabBarPosition,
noRenderContent = _props.noRenderContent,
keyboardShouldPersistTaps = _props.keyboardShouldPersistTaps;
var _state = this.state,
scrollX = _state.scrollX,
scrollValue = _state.scrollValue,
containerWidth = _state.containerWidth;
// let overlayTabs = (this.props.tabBarPosition === 'overlayTop' || this.props.tabBarPosition === 'overlayBottom');
var overlayTabs = false;
var tabBarProps = _extends(_extends({}, this.getTabBarBaseProps()), { keyboardShouldPersistTaps: keyboardShouldPersistTaps, scrollX: scrollX, scrollValue: scrollValue, containerWidth: containerWidth });
if (overlayTabs) {
// tabBarProps.style = {
// position: 'absolute',
// left: 0,
// right: 0,
// [this.props.tabBarPosition === 'overlayTop' ? 'top' : 'bottom']: 0,
// };
}
return React.createElement(
WithTheme,
{ styles: this.props.styles, themeStyles: TabsStyles },
function (styles) {
var content = [React.createElement(
View,
{ key: '$tabbar', style: tabBarPosition === 'top' ? styles.topTabBarSplitLine : styles.bottomTabBarSplitLine },
_this3.renderTabBar(tabBarProps, DefaultTabBar)
), !noRenderContent && _this3.renderContent()];
return React.createElement(
View,
{ style: [styles.container, _this3.props.style], onLayout: _this3.handleLayout },
tabBarPosition === 'top' ? content : content.reverse()
);
}
);
}
}, {
key: 'getTabIndex',
value: function getTabIndex(props) {
var page = props.page,
initialPage = props.initialPage,
tabs = props.tabs;
var param = (page !== undefined ? page : initialPage) || 0;
var index = 0;
if (typeof param === 'string') {
tabs.forEach(function (t, i) {
if (t.key === param) {
index = i;
}
});
} else {
index = param || 0;
}
return index < 0 ? 0 : index;
}
}, {
key: 'UNSAFE_componentWillReceiveProps',
value: function UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.page !== nextProps.page && nextProps.page !== undefined) {
this.goToTab(this.getTabIndex(nextProps), true);
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
this.prevCurrentTab = this.state.currentTab;
}
}, {
key: 'goToTab',
value: function goToTab(index) {
var _this4 = this;
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var newState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (!force && this.nextCurrentTab === index) {
return false;
}
this.nextCurrentTab = index;
var _props2 = this.props,
tabs = _props2.tabs,
onChange = _props2.onChange;
if (index >= 0 && index < tabs.length) {
if (!force) {
// tslint:disable-next-line:no-unused-expression
onChange && onChange(tabs[index], index);
}
this.setState(_extends({ currentTab: index }, newState), function () {
requestAnimationFrame(function () {
_this4.scrollTo(_this4.state.currentTab, _this4.props.animated);
});
});
}
return true;
}
}, {
key: 'tabClickGoToTab',
value: function tabClickGoToTab(index) {
this.goToTab(index);
}
}, {
key: 'getTabBarBaseProps',
value: function getTabBarBaseProps() {
var currentTab = this.state.currentTab;
var _props3 = this.props,
animated = _props3.animated,
onTabClick = _props3.onTabClick,
tabBarActiveTextColor = _props3.tabBarActiveTextColor,
tabBarBackgroundColor = _props3.tabBarBackgroundColor,
tabBarInactiveTextColor = _props3.tabBarInactiveTextColor,
tabBarPosition = _props3.tabBarPosition,
tabBarTextStyle = _props3.tabBarTextStyle,
tabBarUnderlineStyle = _props3.tabBarUnderlineStyle,
renderTab = _props3.renderTab,
renderUnderline = _props3.renderUnderline,
tabs = _props3.tabs;
return {
activeTab: currentTab,
animated: !!animated,
goToTab: this.tabClickGoToTab.bind(this),
onTabClick: onTabClick,
tabBarActiveTextColor: tabBarActiveTextColor,
tabBarBackgroundColor: tabBarBackgroundColor,
tabBarInactiveTextColor: tabBarInactiveTextColor,
tabBarPosition: tabBarPosition,
tabBarTextStyle: tabBarTextStyle,
tabBarUnderlineStyle: tabBarUnderlineStyle,
renderTab: renderTab,
renderUnderline: renderUnderline,
tabs: tabs,
instanceId: this.instanceId
};
}
// tslint:disable-next-line:no-shadowed-variable
}, {
key: 'renderTabBar',
value: function renderTabBar(tabBarProps, DefaultTabBar) {
var renderTabBar = this.props.renderTabBar;
if (renderTabBar === false) {
return null;
} else if (renderTabBar) {
return renderTabBar(tabBarProps);
} else {
return React.createElement(DefaultTabBar, tabBarProps);
}
}
}, {
key: 'getSubElement',
value: function getSubElement(tab, index, subElements) {
var defaultPrefix = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '$i$-';
var allPrefix = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '$ALL$';
var key = tab.key || '' + defaultPrefix + index;
var elements = subElements(defaultPrefix, allPrefix);
var component = elements[key] || elements[allPrefix];
if (component instanceof Function) {
component = component(tab, index);
}
return component || null;
}
}]);
return Tabs;
}(React.PureComponent);
Tabs.defaultProps = {
tabBarPosition: 'top',
initialPage: 0,
swipeable: true,
animated: true,
prerenderingSiblingsNumber: 1,
tabs: [],
destroyInactiveTab: false,
usePaged: true,
tabDirection: 'horizontal',
distanceToChangeTab: 0.3,
style: {}
};
Tabs.DefaultTabBar = DefaultTabBar;