UNPKG

mobile-more

Version:

基于 antd-mobile v5 扩展移动端 UI 组件

135 lines 6.09 kB
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; var _excluded = ["items", "renderItems", "tabsProps", "className", "headerStyle", "headerClassName", "contentStyle", "contentClassName"]; import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react'; import { ceil } from 'ut2'; import { Tabs } from 'antd-mobile'; import { useThrottleFn } from 'rc-hooks'; import { getScrollParent, getScrollTop } from '../../utils/dom'; import classnames from 'classnames'; import { prefixClass } from '../../config'; import "./index.css"; import { getTimestampString } from '../../utils/utils'; var prefixCls = "".concat(prefixClass, "-anchor-tabs"); var BizAnchorTabs = function BizAnchorTabs(_ref) { var items = _ref.items, renderItems = _ref.renderItems, tabsProps = _ref.tabsProps, className = _ref.className, headerStyle = _ref.headerStyle, headerClassName = _ref.headerClassName, contentStyle = _ref.contentStyle, contentClassName = _ref.contentClassName, restProps = _objectWithoutProperties(_ref, _excluded); // TODO 大版本更新改用 React.useId var uid = useMemo(function () { return getTimestampString('__anchor_tabs'); }, []); var ref = useRef(null); var tabContainerRef = useRef(null); var _useState = useState(items[0].key), _useState2 = _slicedToArray(_useState, 2), activeKey = _useState2[0], setActiveKey = _useState2[1]; var _useThrottleFn = useThrottleFn(function () { var _tabContainerRef$curr; var currentKey = items[0].key; var tabContainerRect = (_tabContainerRef$curr = tabContainerRef.current) === null || _tabContainerRef$curr === void 0 ? void 0 : _tabContainerRef$curr.getBoundingClientRect(); var tabTop = tabContainerRect ? tabContainerRect.top + tabContainerRect.height : 0; var _iterator = _createForOfIteratorHelper(items), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var item = _step.value; var element = document.getElementById(uid + item.key); if (!element) continue; var rect = element.getBoundingClientRect(); if (rect.top <= tabTop) { currentKey = item.key; } else { break; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } setActiveKey(currentKey); }, 100), handleScroll = _useThrottleFn.run; useEffect(function () { handleScroll(); var scrollContainer = getScrollParent(ref.current); scrollContainer === null || scrollContainer === void 0 ? void 0 : scrollContainer.addEventListener('scroll', handleScroll); return function () { scrollContainer === null || scrollContainer === void 0 ? void 0 : scrollContainer.removeEventListener('scroll', handleScroll); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); var itemsDom = items.map(function (item) { var id = uid + item.key; if (typeof item.content === 'function') { return /*#__PURE__*/React.createElement(Fragment, { key: item.key }, item.content(id)); } return /*#__PURE__*/React.createElement("div", { key: item.key, id: id }, item.content); }); var customItemsDom = typeof renderItems === 'function' ? renderItems(itemsDom) : itemsDom; return /*#__PURE__*/React.createElement("div", _objectSpread(_objectSpread({ className: classnames(prefixCls, className) }, restProps), {}, { ref: ref }), /*#__PURE__*/React.createElement("div", { className: classnames("".concat(prefixCls, "-header"), headerClassName), style: headerStyle, ref: tabContainerRef }, /*#__PURE__*/React.createElement(Tabs, _objectSpread(_objectSpread({}, tabsProps), {}, { activeKey: activeKey, onChange: function onChange(key) { var _tabsProps$onChange; var id = uid + key; var currentContent = document.getElementById(id); currentContent === null || currentContent === void 0 ? void 0 : currentContent.scrollIntoView(); var scrollContainer = getScrollParent(ref.current); if (scrollContainer && tabContainerRef.current) { var tabRect = tabContainerRef.current.getBoundingClientRect(); // scrollIntoView 存在的问题:不一定滚动至顶部,会留有 0.015xxx 左右的误差 var contentRectTop = (currentContent === null || currentContent === void 0 ? void 0 : currentContent.getBoundingClientRect().top) || 0; var offsetTop = ceil(contentRectTop - tabRect.top); // 如果已滚动至顶部,不需要再处理减去tab高度 // if ( // getScrollTop(scrollContainer) + getClientHeight(scrollContainer) < // getScrollHeight(scrollContainer) // ) { // 此处使用偏差小于tab高度进行判断 if (offsetTop < tabRect.height) { // scrollTo 存在的问题:如果滚动不是整数或0.5倍数会有偏差,例如 400.9121 => 400.5 scrollContainer.scrollTo({ top: getScrollTop(scrollContainer) - tabRect.height + offsetTop }); } } tabsProps === null || tabsProps === void 0 ? void 0 : (_tabsProps$onChange = tabsProps.onChange) === null || _tabsProps$onChange === void 0 ? void 0 : _tabsProps$onChange.call(tabsProps, key); } }), items.map(function (item) { return /*#__PURE__*/React.createElement(Tabs.Tab, { title: item.title, key: item.key }); }))), /*#__PURE__*/React.createElement("div", { className: classnames("".concat(prefixCls, "-content"), contentClassName), style: contentStyle }, customItemsDom)); }; /** * @deprecated 即将废弃,请使用 `BizAnchorTabs` 替代。 */ export var AnchorTabs = BizAnchorTabs; export default BizAnchorTabs;