UNPKG

@nutui/nutui-react

Version:

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

166 lines (165 loc) 7 kB
import { _ as __rest } from "./tslib.es6.js"; import React__default, { useRef, useEffect } from "react"; import classNames from "classnames"; import { JoySmile } from "@nutui/icons-react"; import { C as ComponentDefaults } from "./typings.js"; import TabPane__default from "./TabPane.js"; import { r as requestAniFrame } from "./raf.js"; import { u as usePropsValue, a as useForceUpdate } from "./use-props-value.js"; import { a as useRtl } from "./configprovider2.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, children, onClick, onChange, className, autoHeight, value: outerValue, defaultValue: outerDefaultValue } = _a, rest = __rest(_a, ["activeColor", "tabStyle", "direction", "activeType", "duration", "align", "title", "children", "onClick", "onChange", "className", "autoHeight", "value", "defaultValue"]); const [value, setValue] = usePropsValue({ value: outerValue, defaultValue: outerDefaultValue, finalValue: 0, onChange }); const titleItemsRef = useRef([]); const navRef = useRef(null); const scrollDirection = (nav, to, duration2, direction2) => { let count = 0; const from = direction2 === "horizontal" ? nav.scrollLeft : nav.scrollTop; const frames = Math.round(duration2 * 1e3 / 16); function animate() { if (direction2 === "horizontal") { nav.scrollLeft += (to - from) / frames; } else { nav.scrollTop += (to - from) / frames; } if (++count < frames) { requestAniFrame(animate); } } animate(); }; const scrollIntoView = (index, immediate) => { const nav = navRef.current; const titleItem = titleItemsRef.current; const titlesLength = titles.current.length; const itemLength = titleItemsRef.current.length; if (!nav || !titleItem || !titleItem[itemLength - titlesLength + index]) { return; } const title2 = titleItem[itemLength - titlesLength + index]; let to = 0; if (direction === "vertical") { const runTop = title2.offsetTop - nav.offsetTop + 10; to = runTop - (nav.offsetHeight - title2.offsetHeight) / 2; } else { to = title2.offsetLeft - (nav.offsetWidth - title2.offsetWidth) / 2; } scrollDirection(nav, to, 0.3, direction); }; const getTitles = () => { const titles2 = []; React__default.Children.forEach(children, (child, idx) => { if (React__default.isValidElement(child)) { const props2 = child === null || child === void 0 ? void 0 : child.props; 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-scrollable`]: true, [`${classPrefix}-titles-${align}`]: align }); const tabsActiveStyle = { color: activeType === "smile" ? activeColor : "", background: activeType === "line" ? activeColor : "" }; const getContentStyle = () => { let index = titles.current.findIndex((t) => t.value == 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) => t.value == value); index = index < 0 ? 0 : index; setTimeout(() => { scrollIntoView(index); }); }, [value]); const tabChange = (item) => { onClick && onClick(item.value); if (item.disabled) { return; } setValue(item.value); }; return React__default.createElement( "div", Object.assign({ className: classes }, rest), React__default.createElement("div", { className: classesTitle, style: Object.assign({}, tabStyle), ref: navRef }, !!title && typeof title === "function" ? title() : titles.current.map((item) => { return React__default.createElement( "div", { 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 }), ref: (ref) => titleItemsRef.current.push(ref), key: item.value }, activeType === "line" && React__default.createElement("div", { className: classNames(`${classPrefix}-titles-item-line`, { [`${classPrefix}-titles-item-line-${direction}`]: true }), style: tabsActiveStyle }), activeType === "smile" && React__default.createElement( "div", { className: `${classPrefix}-titles-item-smile`, style: tabsActiveStyle }, React__default.createElement(JoySmile, { color: activeColor, width: 40, height: 20 }) ), React__default.createElement("div", { className: classNames(`${classPrefix}-ellipsis`, `${classPrefix}-titles-item-text`) }, item.title) ); })), React__default.createElement( "div", { className: `${classPrefix}-content-wrap` }, React__default.createElement("div", { className: `${classPrefix}-content`, style: getContentStyle() }, React__default.Children.map(children, (child, idx) => { if (!React__default.isValidElement(child)) { return null; } let childProps = Object.assign(Object.assign({}, child.props), { active: value === child.props.value }); if (String(value) !== String(child.props.value || idx) && autoHeight) { childProps = Object.assign(Object.assign({}, childProps), { autoHeightClassName: "inactive" }); } return React__default.cloneElement(child, childProps); })) ) ); }; Tabs.displayName = "NutTabs"; Tabs.TabPane = TabPane__default; export { Tabs as T };