UNPKG

@nutui/nutui-react-taro

Version:

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

171 lines (170 loc) 7.72 kB
import { _ as __rest } from "./tslib.es6-iWu3F_1J.js"; import React__default, { useRef, useEffect, useState } from "react"; import { View, ScrollView } from "@tarojs/components"; import classNames from "classnames"; import { JoySmile } from "@nutui/icons-react-taro"; import Taro, { nextTick, createSelectorQuery } from "@tarojs/taro"; import { C as ComponentDefaults } from "./typings-DV9RBfhj.js"; import { T as TabPane } from "./tabpane.taro-B8CBhFle.js"; import { u as usePropsValue } from "./use-props-value-SH9krhkx.js"; import { u as useForceUpdate } from "./use-force-update-CudFjCsy.js"; import { r as requestAniFrame } from "./raf-Di10dXPS.js"; import { u as useUuid } from "./use-uuid-BvqmbYZ7.js"; import { a as useRtl } from "./configprovider.taro-DpK4IiCE.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { tabStyle: {}, activeColor: "", direction: "horizontal", activeType: "line", duration: 300, autoHeight: false }); const classPrefix = "nut-tabs"; const Tabs = (props) => { const rtl = useRtl(); const _a = Object.assign(Object.assign({}, defaultProps), props), { activeColor, tabStyle, direction, activeType, duration, align, title, name, children, onClick, onChange, className, autoHeight, value: outerValue, defaultValue: outerDefaultValue } = _a, rest = __rest(_a, ["activeColor", "tabStyle", "direction", "activeType", "duration", "align", "title", "name", "children", "onClick", "onChange", "className", "autoHeight", "value", "defaultValue"]); const uuid = useUuid(); const [value, setValue] = usePropsValue({ value: outerValue, defaultValue: outerDefaultValue, onChange }); const titleItemsRef = useRef([]); const getTitles = () => { const titles2 = []; React__default.Children.forEach(children, (child, idx) => { if (React__default.isValidElement(child)) { const { props: props2 } = child; if ((props2 === null || props2 === void 0 ? void 0 : props2.title) || (props2 === null || props2 === void 0 ? void 0 : props2.value)) { titles2.push({ title: props2.title, value: props2.value || idx, disabled: props2.disabled }); } } }); return titles2; }; const titles = useRef(getTitles()); const forceUpdate = useForceUpdate(); useEffect(() => { titles.current = getTitles(); let current = ""; titles.current.forEach((title2) => { if (title2.value === value) { current = value; } }); if (current !== "" && current !== value) { setValue(current); } else { forceUpdate(); } }, [children]); const classes = classNames(classPrefix, `${classPrefix}-${direction}`, className); const classesTitle = classNames(`${classPrefix}-titles`, { [`${classPrefix}-titles-${activeType}`]: activeType, [`${classPrefix}-titles-${align}`]: align }); const getRect = (selector) => { return new Promise((resolve) => { createSelectorQuery().select(selector).boundingClientRect().exec((rect = []) => { resolve(rect[0]); }); }); }; const getAllRect = (selector) => { return new Promise((resolve) => { createSelectorQuery().selectAll(selector).boundingClientRect().exec((rect = []) => { resolve(rect[0]); }); }); }; const scrollWithAnimation = useRef(false); const [scrollLeft, setScrollLeft] = useState(0); const [scrollTop, setScrollTop] = useState(0); const scrollDirection = (to, direction2) => { if (direction2 === "horizontal") setScrollLeft(to); else setScrollTop(to); }; const scrollIntoView = (index) => { requestAniFrame(() => { Promise.all([ getRect(`#nut-tabs-titles-${name || uuid} .nut-tabs-list`), getAllRect(`#nut-tabs-titles-${name || uuid} .nut-tabs-titles-item`) ]).then(([navRect, titleRects]) => { const titleRect = titleRects[index]; if (!titleRect) return; let to = 0; if (direction === "vertical") { const top = titleRects.slice(0, index).reduce((prev, curr) => prev + curr.height, 0); to = top - (navRect.height - titleRect.height) / 2; } else { const left = titleRects.slice(0, index).reduce((prev, curr) => prev + curr.width, 0); to = left - (navRect.width - titleRect.width) / 2; } scrollDirection(to, direction); nextTick(() => { scrollWithAnimation.current = true; }); }); }); }; const getContentStyle = () => { let index = titles.current.findIndex((t) => String(t.value) === String(value)); index = index < 0 ? 0 : index; return { transform: direction === "horizontal" ? `translate3d(${rtl ? "" : "-"}${index * 100}%, 0, 0)` : `translate3d( 0, -${index * 100}%, 0)`, transitionDuration: `${duration}ms` }; }; useEffect(() => { let index = titles.current.findIndex((t) => String(t.value) === String(value)); index = index < 0 ? 0 : index; scrollIntoView(index); }, [value]); const tabChange = (item) => { onClick && onClick(item.value); if (!item.disabled) { setValue(item.value); } }; return React__default.createElement( View, Object.assign({ className: classes }, rest), React__default.createElement( ScrollView, { enableFlex: true, scrollX: direction === "horizontal", scrollY: direction === "vertical", scrollLeft, scrollTop, enhanced: true, showScrollbar: false, scrollWithAnimation: rtl && Taro.getEnv() !== "WEB" ? false : scrollWithAnimation.current, id: `nut-tabs-titles-${name || uuid}`, className: classesTitle, style: tabStyle }, React__default.createElement(View, { className: "nut-tabs-list" }, !!title && typeof title === "function" ? title() : titles.current.map((item, index) => { return React__default.createElement( View, { key: item.value, ref: (ref) => titleItemsRef.current.push(ref), id: `scrollIntoView${index}`, onClick: () => tabChange(item), className: classNames(`${classPrefix}-titles-item`, { [`nut-tabs-titles-item-active`]: !item.disabled && String(item.value) === String(value), [`nut-tabs-titles-item-disabled`]: item.disabled, [`nut-tabs-titles-item-${align}`]: align }) }, activeType === "line" && React__default.createElement(View, { className: classNames(`${classPrefix}-titles-item-line`, `${classPrefix}-titles-item-line-${direction}`), style: { background: activeColor } }), activeType === "smile" && React__default.createElement( View, { className: `${classPrefix}-titles-item-smile` }, React__default.createElement(JoySmile, { color: activeColor }) ), React__default.createElement(View, { className: classNames({ [`${classPrefix}-ellipsis`]: direction === "vertical" }, `${classPrefix}-titles-item-text`), style: { color: activeColor } }, item.title) ); })) ), React__default.createElement( View, { className: `${classPrefix}-content-wrap` }, React__default.createElement(View, { className: `${classPrefix}-content`, style: getContentStyle() }, React__default.Children.map(children, (child, idx) => { if (!React__default.isValidElement(child)) return null; return React__default.cloneElement(child, Object.assign(Object.assign({}, child.props), { active: value === child.props.value, autoHeightClassName: autoHeight && String(value) !== String(child.props.value || idx) ? "inactive" : void 0 })); })) ) ); }; Tabs.displayName = "NutTabs"; Tabs.TabPane = TabPane; export { Tabs as T };