@jdcfe/yep-react
Version:
一套移动端的React组件库
415 lines (364 loc) • 15 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/inherits";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
import * as React from 'react';
import classNames from 'classnames';
import noop from '../_utils/noop';
import Gesture from '../gesture';
import { getTransformPropValue, setPxStyle, setTransform } from '../_utils/styleUtil';
import DefaultTabBar from './DefaultTabBar';
import TabPanel from './TabPanel';
var getPanDirection = function getPanDirection(direction) {
switch (direction) {
case 2:
case 4:
return 'horizontal';
case 8:
case 16:
return 'vertical';
default:
return 'none';
}
};
var Tabs = /*#__PURE__*/function (_React$PureComponent) {
_inherits(Tabs, _React$PureComponent);
var _super = _createSuper(Tabs);
function Tabs(props) {
var _this;
_classCallCheck(this, Tabs);
_this = _super.call(this, props);
_this.onPan = function () {
var lastOffset = 0;
var finalOffset = 0;
var panDirection;
var getLastOffset = function getLastOffset() {
var isVertical = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this.isTabVertical();
var offset = +"".concat(lastOffset).replace('%', '');
if ("".concat(lastOffset).indexOf('%') >= 0) {
offset /= 100;
offset *= isVertical ? _this.layout.clientHeight : _this.layout.clientWidth;
}
return offset;
};
return {
onPanStart: function onPanStart(status) {
if (!_this.props.swipeable || !_this.props.animated) return;
panDirection = getPanDirection(status.direction);
_this.setState({
isMoving: true
});
},
onPanMove: function onPanMove(status) {
var _this$props = _this.props,
swipeable = _this$props.swipeable,
animated = _this$props.animated;
if (!status.moveStatus || !_this.layout || !swipeable || !animated) return;
var isVertical = _this.isTabVertical();
var offset = getLastOffset();
if (isVertical) {
offset += panDirection === 'horizontal' ? 0 : status.moveStatus.y;
} else {
offset += panDirection === 'vertical' ? 0 : status.moveStatus.x;
}
var canScrollOffset = isVertical ? -_this.layout.scrollHeight + _this.layout.clientHeight : -_this.layout.scrollWidth + _this.layout.clientWidth;
offset = Math.min(offset, 0);
offset = Math.max(offset, canScrollOffset);
setPxStyle(_this.layout, offset, 'px', isVertical);
finalOffset = offset;
},
onPanEnd: function onPanEnd() {
if (!_this.props.swipeable || !_this.props.animated) return;
lastOffset = finalOffset;
var isVertical = _this.isTabVertical();
var offsetIndex = _this.getOffsetIndex(finalOffset, isVertical ? _this.layout.clientHeight : _this.layout.clientWidth);
_this.setState({
isMoving: false
});
if (offsetIndex === _this.state.currentTab) {
if (_this.props.usePaged) {
setTransform(_this.layout.style, _this.getContentPosByIndex(offsetIndex, _this.isTabVertical()));
}
} else {
_this.goToTab(offsetIndex);
}
},
setCurrentOffset: function setCurrentOffset(offset) {
return lastOffset = offset;
}
};
}();
_this.getOffsetIndex = function (current, width) {
var threshold = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _this.props.distanceToChangeTab;
var ratio = Math.abs(current / width);
var direction = ratio >= _this.state.currentTab ? '<' : '>';
var distance = direction === '>' ? Math.abs(width % current) : Math.abs(current % width);
var index = Math.floor(ratio);
switch (direction) {
case '<':
return distance > threshold ? index + 1 : index;
case '>':
return distance < threshold ? index + 1 : index;
default:
return Math.round(ratio);
}
};
_this.renderTabBar = _this.renderTabBar.bind(_assertThisInitialized(_this));
_this.renderContent = _this.renderContent.bind(_assertThisInitialized(_this));
_this.isTabVertical = _this.isTabVertical.bind(_assertThisInitialized(_this));
_this.getTabIndex = _this.getTabIndex.bind(_assertThisInitialized(_this));
_this.getContentPosByIndex = _this.getContentPosByIndex.bind(_assertThisInitialized(_this));
_this.createContentLayoutRef = _this.createContentLayoutRef.bind(_assertThisInitialized(_this));
_this.onSwipe = _this.onSwipe.bind(_assertThisInitialized(_this));
_this.goToTab = _this.goToTab.bind(_assertThisInitialized(_this));
_this.tabClickGoToTab = _this.tabClickGoToTab.bind(_assertThisInitialized(_this));
_this.getOffsetIndex = _this.getOffsetIndex.bind(_assertThisInitialized(_this));
_this.state = {
isMoving: false,
currentTab: _this.getTabIndex(props),
contentPos: _this.getContentPosByIndex(_this.getTabIndex(props), _this.isTabVertical(props.tabDirection))
};
return _this;
}
_createClass(Tabs, [{
key: "componentDidMount",
value: function componentDidMount() {
this.prevCurrentTab = this.state.currentTab;
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
this.prevCurrentTab = this.state.currentTab;
}
}, {
key: "getTabIndex",
value: function getTabIndex(props) {
var page = props.page,
defaultIndex = props.defaultIndex;
var param = (page !== undefined ? page : defaultIndex) || 0;
var index = param || 0;
return index < 0 ? 0 : index;
}
}, {
key: "getContentPosByIndex",
value: function getContentPosByIndex(index, isVertical) {
var value = "".concat(-index * 100, "%");
this.onPan.setCurrentOffset(value);
var translate = isVertical ? "0px, ".concat(value) : "".concat(value, ", 0px"); // fix: content overlay TabBar on iOS 10. ( 0px -> 1px )
return "translate3d(".concat(translate, ", 1px)");
}
}, {
key: "isTabVertical",
value: function isTabVertical() {
var direction = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props.tabDirection;
return direction === 'vertical';
}
}, {
key: "createContentLayoutRef",
value: function createContentLayoutRef(el) {
this.layout = el;
}
}, {
key: "tabClickGoToTab",
value: function tabClickGoToTab(index) {
this.goToTab(index, false, true);
}
}, {
key: "goToTab",
value: function goToTab(index) {
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var usePaged = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.props.usePaged;
var tabDirection = this.props.tabDirection;
var newState = {};
if (usePaged) {
newState = {
contentPos: this.getContentPosByIndex(index, this.isTabVertical(tabDirection))
};
}
if (!force && this.nextCurrentTab === index) {
return false;
}
this.nextCurrentTab = index;
var _this$props2 = this.props,
children = _this$props2.children,
onChange = _this$props2.onChange;
if (index >= 0 && index < React.Children.count(children)) {
if (!force) {
if (onChange) {
onChange(index);
}
if (this.props.page !== undefined) {
return false;
}
}
this.setState(Object.assign({
currentTab: index
}, newState));
}
return true;
}
}, {
key: "onSwipe",
value: function onSwipe(e) {
var _this$props3 = this.props,
tabBarPosition = _this$props3.tabBarPosition,
swipeable = _this$props3.swipeable,
usePaged = _this$props3.usePaged;
if (!swipeable || !usePaged || this.isTabVertical()) return;
switch (tabBarPosition) {
case 'top':
case 'bottom':
switch (e.direction) {
case 2:
if (!this.isTabVertical()) {
this.goToTab(this.prevCurrentTab + 1);
}
case 8:
if (this.isTabVertical()) {
this.goToTab(this.prevCurrentTab + 1);
}
break;
case 4:
if (!this.isTabVertical()) {
this.goToTab(this.prevCurrentTab - 1);
}
case 16:
if (this.isTabVertical()) {
this.goToTab(this.prevCurrentTab - 1);
}
break;
}
break;
}
}
}, {
key: "getTabBarBaseProps",
value: function getTabBarBaseProps() {
var currentTab = this.state.currentTab;
var _this$props4 = this.props,
animated = _this$props4.animated,
onTabClick = _this$props4.onTabClick,
tabBarActiveTextColor = _this$props4.tabBarActiveTextColor,
tabBarBackgroundColor = _this$props4.tabBarBackgroundColor,
tabBarInactiveTextColor = _this$props4.tabBarInactiveTextColor,
tabBarPosition = _this$props4.tabBarPosition,
tabBarTextStyle = _this$props4.tabBarTextStyle,
tabBarUnderlineStyle = _this$props4.tabBarUnderlineStyle,
children = _this$props4.children;
var tabs = React.Children.map(children, function (child, index) {
return {
title: child.props.tab,
key: index
};
});
return {
activeTab: currentTab,
animated: animated,
goToTab: this.tabClickGoToTab,
onTabClick: onTabClick,
tabBarActiveTextColor: tabBarActiveTextColor,
tabBarBackgroundColor: tabBarBackgroundColor,
tabBarInactiveTextColor: tabBarInactiveTextColor,
tabBarPosition: tabBarPosition,
tabBarTextStyle: tabBarTextStyle,
tabBarUnderlineStyle: tabBarUnderlineStyle,
tabs: tabs
};
}
}, {
key: "renderTabBar",
value: function renderTabBar(tabBarProps) {
var renderTabBar = this.props.renderTabBar;
if (renderTabBar === false) {
return null;
} else if (renderTabBar) {
return renderTabBar(tabBarProps);
} else {
return /*#__PURE__*/React.createElement(DefaultTabBar, tabBarProps);
}
}
}, {
key: "renderContent",
value: function renderContent() {
var _classNames;
var _this$props5 = this.props,
prefixCls = _this$props5.prefixCls,
animated = _this$props5.animated,
children = _this$props5.children;
var _this$state = this.state,
isMoving = _this$state.isMoving,
currentTab = _this$state.currentTab,
contentPos = _this$state.contentPos;
var isTabVertical = this.isTabVertical();
var cls = classNames((_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-content-wrap"), true), _defineProperty(_classNames, "".concat(prefixCls, "-content-wrap-animated"), animated && !isMoving), _classNames));
var contentStyle = animated ? getTransformPropValue(contentPos) : Object.assign({
position: 'relative'
}, this.isTabVertical() ? {
top: "".concat(-currentTab * 100, "%")
} : {
left: "".concat(-currentTab * 100, "%")
});
return /*#__PURE__*/React.createElement("div", {
className: cls,
style: contentStyle,
ref: this.createContentLayoutRef
}, React.Children.map(children, function (child, index) {
var _classNames2;
var panelCls = classNames((_classNames2 = {}, _defineProperty(_classNames2, "".concat(prefixCls, "-pane-wrap"), true), _defineProperty(_classNames2, "".concat(prefixCls, "-pane-wrap-").concat(currentTab === index ? '' : 'in', "active"), true), _classNames2));
return /*#__PURE__*/React.cloneElement(child, Object.assign(Object.assign({}, child.props), {
className: panelCls,
active: currentTab === index,
fixX: isTabVertical,
fixY: !isTabVertical
}), child.props.children);
}));
}
}, {
key: "render",
value: function render() {
var _this$props6 = this.props,
prefixCls = _this$props6.prefixCls,
className = _this$props6.className,
style = _this$props6.style,
tabDirection = _this$props6.tabDirection,
tabBarPosition = _this$props6.tabBarPosition;
var cls = classNames(prefixCls, className, "".concat(prefixCls, "-").concat(tabDirection), "".concat(prefixCls, "-").concat(tabBarPosition));
var tabBarProps = Object.assign({}, this.getTabBarBaseProps());
var content = [/*#__PURE__*/React.createElement("div", {
key: "tabBar",
className: "".concat(prefixCls, "-tab-bar-wrap")
}, this.renderTabBar(tabBarProps)), /*#__PURE__*/React.createElement(Gesture, _extends({
key: "$content",
onSwipe: this.onSwipe
}, this.onPan), this.renderContent())];
return /*#__PURE__*/React.createElement("div", {
className: cls,
style: style
}, tabBarPosition === 'top' || tabBarPosition === 'left' ? content : content.reverse());
}
}]);
return Tabs;
}(React.PureComponent);
export { Tabs as default };
Tabs.defaultProps = {
prefixCls: 'Yep-tabs',
style: {},
defaultIndex: 0,
className: '',
onChange: noop,
tabBarPosition: 'top',
tabDirection: 'horizontal',
animated: true,
swipeable: true,
usePaged: true,
onTabClick: noop,
distanceToChangeTab: 0
};
Tabs.TabPanel = TabPanel;
Tabs.DefaultTabBar = DefaultTabBar;