UNPKG

@nutui/nutui-react-taro

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

231 lines (230 loc) 10.8 kB
import { _ as _define_property } from "@swc/helpers/_/_define_property"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import React, { useEffect, useRef, useState } from "react"; import { ScrollView, View } from "@tarojs/components"; import classNames from "classnames"; import { JoySmile } from "@nutui/icons-react-taro"; import Taro, { createSelectorQuery, nextTick } from "@tarojs/taro"; import { ComponentDefaults } from "../../utils/typings"; import TabPane from "../tabpane/index"; import { usePropsValue } from "../../hooks/use-props-value"; import { useForceUpdate } from "../../hooks/use-force-update"; import raf from "../../utils/raf"; import { useUuid } from "../../hooks/use-uuid"; import { useRtl } from "../configprovider/configprovider"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { tabStyle: {}, activeColor: '', direction: 'horizontal', activeType: 'line', duration: 300, autoHeight: false }); var classPrefix = 'nut-tabs'; export var Tabs = function(props) { var rtl = useRtl(); var _ref = _object_spread({}, defaultProps, props), activeColor = _ref.activeColor, tabStyle = _ref.tabStyle, direction = _ref.direction, activeType = _ref.activeType, duration = _ref.duration, align = _ref.align, title = _ref.title, name = _ref.name, children = _ref.children, onClick = _ref.onClick, onChange = _ref.onChange, className = _ref.className, autoHeight = _ref.autoHeight, outerValue = _ref.value, outerDefaultValue = _ref.defaultValue, rest = _object_without_properties(_ref, [ "activeColor", "tabStyle", "direction", "activeType", "duration", "align", "title", "name", "children", "onClick", "onChange", "className", "autoHeight", "value", "defaultValue" ]); var uuid = useUuid(); var _usePropsValue = _sliced_to_array(usePropsValue({ value: outerValue, defaultValue: outerDefaultValue, onChange: onChange }), 2), value = _usePropsValue[0], setValue = _usePropsValue[1]; var titleItemsRef = useRef([]); var getTitles = function() { var titles = []; React.Children.forEach(children, function(child, idx) { if (/*#__PURE__*/ React.isValidElement(child)) { var _$props = child.props; if ((_$props === null || _$props === void 0 ? void 0 : _$props.title) || (_$props === null || _$props === void 0 ? void 0 : _$props.value)) { titles.push({ title: _$props.title, value: _$props.value || idx, disabled: _$props.disabled }); } } }); return titles; }; var titles = useRef(getTitles()); var forceUpdate = useForceUpdate(); useEffect(function() { titles.current = getTitles(); var current = ''; titles.current.forEach(function(title) { if (title.value === value) { current = value; } }); if (current !== '' && current !== value) { setValue(current); } else { forceUpdate(); } }, [ children ]); var classes = classNames(classPrefix, "".concat(classPrefix, "-").concat(direction), className); var _obj; var classesTitle = classNames("".concat(classPrefix, "-titles"), (_obj = {}, _define_property(_obj, "".concat(classPrefix, "-titles-").concat(activeType), activeType), _define_property(_obj, "".concat(classPrefix, "-titles-").concat(align), align), _obj)); var getRect = function(selector) { return new Promise(function(resolve) { createSelectorQuery().select(selector).boundingClientRect().exec(function() { var rect = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : []; resolve(rect[0]); }); }); }; var getAllRect = function(selector) { return new Promise(function(resolve) { createSelectorQuery().selectAll(selector).boundingClientRect().exec(function() { var rect = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : []; resolve(rect[0]); }); }); }; var scrollWithAnimation = useRef(false); var _useState = _sliced_to_array(useState(0), 2), scrollLeft = _useState[0], setScrollLeft = _useState[1]; var _useState1 = _sliced_to_array(useState(0), 2), scrollTop = _useState1[0], setScrollTop = _useState1[1]; var scrollDirection = function(to, direction) { // 使用ScrollView组件此处不需要手动raf scrollLeft if (direction === 'horizontal') setScrollLeft(to); else setScrollTop(to); }; var scrollIntoView = function(index) { raf(function() { Promise.all([ getRect("#nut-tabs-titles-".concat(name || uuid)), getAllRect("#nut-tabs-titles-".concat(name || uuid, " .nut-tabs-titles-item")) ]).then(function(param) { var _param = _sliced_to_array(param, 2), navRect = _param[0], titleRects = _param[1]; var titleRect = titleRects[index]; if (!titleRect) return; var to = 0; if (direction === 'vertical') { var totalHeight = titleRects.reduce(function(sum, curr) { return sum + curr.height; }, 0); var top = titleRects.slice(0, index).reduce(function(prev, curr) { return prev + curr.height; }, 0); to = Math.min(Math.max(0, top - (navRect.height - titleRect.height) / 2), totalHeight - navRect.height); } else { var totalWidth = titleRects.reduce(function(sum, curr) { return sum + curr.width; }, 0); var left = titleRects.slice(0, index).reduce(function(prev, curr) { return prev + curr.width; }, 0); to = Math.min(Math.max(0, left - (navRect.width - titleRect.width) / 2), totalWidth - navRect.width); } scrollDirection(to, direction); nextTick(function() { scrollWithAnimation.current = true; }); }); }); }; var getContentStyle = function() { var index = titles.current.findIndex(function(t) { return String(t.value) === String(value); }); index = index < 0 ? 0 : index; return { transform: direction === 'horizontal' ? "translate3d(".concat(rtl ? '' : '-').concat(index * 100, "%, 0, 0)") : "translate3d( 0, -".concat(index * 100, "%, 0)"), transitionDuration: "".concat(duration, "ms") }; }; useEffect(function() { var index = titles.current.findIndex(function(t) { return String(t.value) === String(value); }); index = index < 0 ? 0 : index; scrollIntoView(index); }, [ value ]); var tabChange = function(item) { onClick && onClick(item.value); if (!item.disabled) { setValue(item.value); } }; return /*#__PURE__*/ React.createElement(View, _object_spread({ className: classes }, rest), /*#__PURE__*/ React.createElement(ScrollView, { enableFlex: true, scrollX: direction === 'horizontal', scrollY: direction === 'vertical', scrollLeft: scrollLeft, scrollTop: scrollTop, enhanced: true, showScrollbar: false, scrollWithAnimation: rtl && Taro.getEnv() !== 'WEB' ? false : scrollWithAnimation.current, id: "nut-tabs-titles-".concat(name || uuid), className: classesTitle, style: tabStyle }, /*#__PURE__*/ React.createElement(View, { className: "nut-tabs-list" }, !!title && typeof title === 'function' ? title() : titles.current.map(function(item, index) { var _obj; return /*#__PURE__*/ React.createElement(View, { key: item.value, ref: function(ref) { return titleItemsRef.current.push(ref); }, id: "scrollIntoView".concat(index), onClick: function() { return tabChange(item); }, className: classNames("".concat(classPrefix, "-titles-item"), (_obj = {}, _define_property(_obj, "nut-tabs-titles-item-active", !item.disabled && String(item.value) === String(value)), _define_property(_obj, "nut-tabs-titles-item-disabled", item.disabled), _define_property(_obj, "nut-tabs-titles-item-".concat(align), align), _obj)) }, activeType === 'line' && /*#__PURE__*/ React.createElement(View, { className: classNames("".concat(classPrefix, "-titles-item-line"), "".concat(classPrefix, "-titles-item-line-").concat(direction)), style: { background: activeColor } }), activeType === 'smile' && /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-titles-item-smile") }, /*#__PURE__*/ React.createElement(JoySmile, { color: activeColor })), /*#__PURE__*/ React.createElement(View, { className: classNames(_define_property({}, "".concat(classPrefix, "-ellipsis"), direction === 'vertical'), "".concat(classPrefix, "-titles-item-text")), style: { color: activeColor } }, item.title)); }))), /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-content-wrap") }, /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-content"), style: getContentStyle() }, React.Children.map(children, function(child, idx) { if (!/*#__PURE__*/ React.isValidElement(child)) return null; return /*#__PURE__*/ React.cloneElement(child, _object_spread_props(_object_spread({}, child.props), { active: value === child.props.value, autoHeightClassName: autoHeight && String(value) !== String(child.props.value || idx) ? 'inactive' : undefined })); })))); }; Tabs.displayName = 'NutTabs'; Tabs.TabPane = TabPane;