UNPKG

@jdcfe/yep-react

Version:

一套移动端的React组件库

415 lines (364 loc) 15 kB
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;