zarm
Version:
基于 React 的移动端UI库
307 lines (249 loc) • 11.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _bem = require("@zarm-design/bem");
var React = _interopRequireWildcard(require("react"));
var _carousel = _interopRequireDefault(require("../carousel"));
var _configProvider = require("../config-provider");
var _deprecationWarning = require("../utils/deprecationWarning");
var _dom = require("../utils/dom");
var _TabPanel = _interopRequireDefault(require("./TabPanel"));
var _index = require("./util/index");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) { if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } } return n.default = e, t && t.set(e, n), n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var getChildChecked = function getChildChecked(children) {
var selectIndex;
React.Children.forEach(children, function (item, index) {
if ( /*#__PURE__*/React.isValidElement(item) && item.props && item.props.selected) {
selectIndex = index;
}
});
return selectIndex;
};
var parseValueBoundary = function parseValueBoundary(inputValue, children) {
var count = React.Children.count(children);
if (inputValue <= 0) {
return 0;
}
if (inputValue > count - 1) {
return count - 1;
}
return inputValue;
};
var getValue = function getValue(props, defaultValue) {
if (typeof props.value !== 'undefined') {
return parseValueBoundary(props.value, props.children);
}
if (typeof props.defaultValue !== 'undefined') {
return parseValueBoundary(props.defaultValue, props.children);
}
if (getChildChecked(props.children)) {
return parseValueBoundary(getChildChecked(props.children), props.children);
}
return parseValueBoundary(defaultValue, props.children);
};
var Tabs = /*#__PURE__*/React.forwardRef(function (props, ref) {
var _ref;
var className = props.className,
style = props.style,
value = props.value,
defaultValue = props.defaultValue,
disabled = props.disabled,
swipeable = props.swipeable,
scrollable = props.scrollable,
direction = props.direction,
lineWidth = props.lineWidth,
onChange = props.onChange,
children = props.children; // TODO: DeprecationWarning - remove this warning in next major version
(0, _deprecationWarning.useTypeChangeWarning)(['vertical', 'horizontal'].includes(direction), 'Tabs', 'direction', direction, "'top' | 'right' | 'bottom' | 'left'");
var carouselRef = React.useRef(null);
var tablistRef = React.useRef(null);
var _React$useState = React.useState(0),
_React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
itemWidth = _React$useState2[0],
setItemWidth = _React$useState2[1];
var _React$useState3 = React.useState(getValue({
value: value,
defaultValue: defaultValue,
children: children
}, 0)),
_React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
currentValue = _React$useState4[0],
setCurrentValue = _React$useState4[1];
var _React$useContext = React.useContext(_configProvider.ConfigContext),
prefixCls = _React$useContext.prefixCls;
var bem = (0, _bem.createBEM)('tabs', {
prefixCls: prefixCls
}); // TODO: direction='vertical' 暂作兼容
var isVertical = ['left', 'right', 'vertical'].includes(direction);
var parseValue = React.useCallback(function (inputValue) {
return parseValueBoundary(inputValue, children);
}, [children]);
var classes = bem([(_ref = {}, (0, _defineProperty2.default)(_ref, "".concat(direction), true), (0, _defineProperty2.default)(_ref, "scroll", scrollable), _ref), className]); // 计算 line 大小和位置
var caclLineSizePos = function caclLineSizePos() {
var newValue = parseValue(currentValue);
var ChildCount = React.Children.count(children);
var pos = 100 * newValue;
if (scrollable && tablistRef.current) {
var el = tablistRef.current.children[newValue];
var _ref2 = el,
_ref2$offsetLeft = _ref2.offsetLeft,
offsetLeft = _ref2$offsetLeft === void 0 ? 0 : _ref2$offsetLeft,
_ref2$offsetTop = _ref2.offsetTop,
offsetTop = _ref2$offsetTop === void 0 ? 0 : _ref2$offsetTop;
pos = isVertical ? offsetTop : offsetLeft;
}
var size = scrollable ? "".concat(itemWidth, "px") : "".concat(100 / ChildCount, "%");
var transformValue = scrollable ? (0, _index.getPxStyle)(pos, 'px', isVertical) : (0, _index.getPxStyle)(pos, '%', isVertical);
var styleUl = (0, _index.getTransformPropValue)(transformValue);
var itemSize = isVertical ? {
height: "".concat(size)
} : {
width: "".concat(size)
};
return _objectSpread(_objectSpread({}, styleUl), itemSize);
};
var onTabChange = React.useCallback(function (newValue) {
if (typeof value === 'undefined') {
setCurrentValue(newValue);
}
typeof onChange === 'function' && onChange(newValue);
}, [value, onChange]);
var onTabClick = function onTabClick(tab, index) {
if (disabled || tab.props.disabled) {
return;
}
if (swipeable) {
carouselRef.current && carouselRef.current.onSlideTo(index);
return;
}
onTabChange(index);
};
var lineStyle = caclLineSizePos();
var lineInnerRender;
if (lineWidth) {
lineStyle.backgroundColor = 'transparent';
lineInnerRender = /*#__PURE__*/React.createElement("span", {
className: bem('line__inner'),
style: {
width: lineWidth
}
});
} // 渲染内容
var contentRender;
if (swipeable) {
contentRender = /*#__PURE__*/React.createElement(_carousel.default, {
swipeable: !disabled,
direction: isVertical ? 'vertical' : 'horizontal',
showPagination: false,
activeIndex: parseValue(currentValue),
ref: carouselRef,
onChange: onTabChange
}, React.Children.map(children, function (item, index) {
return /*#__PURE__*/React.createElement("div", {
key: +index
}, item.props.children);
}));
} else {
contentRender = React.Children.map(children, function (item, index) {
return /*#__PURE__*/React.createElement(_TabPanel.default, (0, _extends2.default)({}, item.props, {
selected: parseValue(currentValue) === index
}));
});
}
var renderTabs = function renderTabs(tab, index) {
var itemCls = bem('tab', [{
disabled: disabled || tab.props.disabled,
active: parseValue(currentValue) === index
}, tab.props.className]);
return /*#__PURE__*/React.createElement("li", {
role: "tab",
key: +index,
className: itemCls,
onClick: function onClick() {
return onTabClick(tab, index);
}
}, tab.props.title);
}; // 渲染选项
var tabsRender = React.Children.map(children, renderTabs);
var getItemStyle = function getItemStyle(el, prop) {
var newValue = '0';
if (prop in el.style) {
newValue = el.style[prop] || window.getComputedStyle(el).getPropertyValue(prop) || '0';
}
return newValue;
};
var calculateLineWidth = React.useCallback(function () {
if (!scrollable) {
return;
}
var newValue = parseValue(currentValue);
var el = tablistRef.current.children[newValue];
var size = isVertical ? getItemStyle(el, 'height') : getItemStyle(el, 'width');
setItemWidth(parseInt(size.toString(), 10));
}, [parseValue, currentValue, isVertical, scrollable]);
var calculateScorllLeftLocation = React.useCallback(function () {
if (!scrollable) {
return false;
}
var newValue = parseValue(currentValue);
var prevTabItem = tablistRef.current.childNodes[newValue];
if (scrollable && tablistRef.current && prevTabItem) {
var _tablistRef$current = tablistRef.current,
_tablistRef$current$o = _tablistRef$current.offsetWidth,
layoutOffsetWidth = _tablistRef$current$o === void 0 ? 0 : _tablistRef$current$o,
_tablistRef$current$o2 = _tablistRef$current.offsetHeight,
layoutOffsetHeight = _tablistRef$current$o2 === void 0 ? 0 : _tablistRef$current$o2;
var left = prevTabItem.offsetLeft + prevTabItem.offsetWidth / 2 - layoutOffsetWidth / 2;
var top = prevTabItem.offsetTop + prevTabItem.offsetHeight / 2 - layoutOffsetHeight / 2;
(0, _dom.scrollTo)(tablistRef.current, top, left, 0.3);
}
}, [parseValue, currentValue, scrollable]);
React.useEffect(function () {
if (React.Children.count(children)) {
calculateLineWidth();
calculateScorllLeftLocation();
}
}, [calculateLineWidth, calculateScorllLeftLocation, children]);
React.useEffect(function () {
setCurrentValue(getValue({
value: value,
defaultValue: defaultValue,
children: children
}, 0));
}, [value, defaultValue, children]);
return /*#__PURE__*/React.createElement("div", {
ref: ref,
className: classes,
style: style
}, /*#__PURE__*/React.createElement("div", {
className: bem('header')
}, /*#__PURE__*/React.createElement("ul", {
className: bem('tablist'),
role: "tablist",
ref: tablistRef
}, tabsRender, /*#__PURE__*/React.createElement("div", {
className: bem('line'),
style: lineStyle
}, lineInnerRender))), /*#__PURE__*/React.createElement("div", {
className: bem('body')
}, contentRender));
});
Tabs.displayName = 'Tabs';
Tabs.defaultProps = {
disabled: false,
swipeable: false,
scrollable: false,
direction: 'top'
};
var _default = Tabs;
exports.default = _default;