UNPKG

@mijadesign/mjui-react-taro

Version:

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

210 lines (209 loc) 9.27 kB
import { _ as __rest } from "./tslib.es6-iWu3F_1J.js"; import classNames from "classnames"; import React, { useRef, useEffect, useState } from "react"; import { useRtl, TabPane } from "@nutui/nutui-react-taro"; import { C as ComponentDefaults } from "./typings-DV9RBfhj.js"; import { u as usePropsValue, a as useForceUpdate } from "./use-props-value-DuhZMy4U.js"; import { View, ScrollView } from "@tarojs/components"; import Taro, { nextTick, createSelectorQuery } from "@tarojs/taro"; function requestAniFrame() { if (typeof window !== "undefined") { const _window = window; return _window.requestAnimationFrame || _window.webkitRequestAnimationFrame || function(callback) { _window.setTimeout(callback, 1e3 / 60); }; } return (callback) => { setTimeout(callback, 1e3 / 60); }; } const raf = requestAniFrame(); const idCounter = {}; function uniqueId(prefix = "$nut$") { if (!idCounter[prefix]) { idCounter[prefix] = 0; } const id = ++idCounter[prefix]; if (prefix === "$nut$") { return `${id}`; } return `${prefix}${id}`; } function useUuid() { const idRef = useRef(uniqueId()); return idRef.current; } const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { tabStyle: {}, activeColor: "", direction: "horizontal", activeType: "line", actionButtonProps: { fill: "outline" }, duration: 300, autoHeight: false, contentAnimation: true }); const classPrefix = "nut-tabs"; const Tabs$1 = (props) => { const rtl = useRtl(); const _a = Object.assign(Object.assign({}, defaultProps), props), { activeColor, tabStyle, direction, activeType, actionButtonProps, duration, align, title, name, children, onClick, onChange, className, autoHeight, value: outerValue, defaultValue: outerDefaultValue, contentAnimation } = _a, rest = __rest(_a, ["activeColor", "tabStyle", "direction", "activeType", "actionButtonProps", "duration", "align", "title", "name", "children", "onClick", "onChange", "className", "autoHeight", "value", "defaultValue", "contentAnimation"]); const uuid = useUuid(); const [value, setValue] = usePropsValue({ value: outerValue, defaultValue: outerDefaultValue, onChange }); const titleItemsRef = useRef([]); const getTitles = () => { const titles2 = []; React.Children.forEach(children, (child, idx) => { if (React.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-${activeType}-${actionButtonProps.fill}`]: activeType === "button", [`${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) => { raf(() => { 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; if (!contentAnimation) return {}; 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.createElement( View, Object.assign({ className: classes }, rest), React.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.createElement(View, { className: "nut-tabs-list" }, !!title && typeof title === "function" ? title() : titles.current.map((item, index) => { return React.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.createElement(View, { className: classNames(`${classPrefix}-titles-item-line`, `${classPrefix}-titles-item-line-${direction}`), style: { background: activeColor } }), React.createElement(View, { className: classNames({ [`${classPrefix}-ellipsis`]: direction === "vertical" }, `${classPrefix}-titles-item-text`), style: { color: activeColor } }, item.title) ); })) ), React.createElement( View, { className: `${classPrefix}-content-wrap` }, React.createElement(View, { className: classNames(`${classPrefix}-content`, contentAnimation ? "" : `${classPrefix}-content-no-animate`), style: getContentStyle() }, React.Children.map(children, (child, idx) => { if (!React.isValidElement(child)) return null; const isActive = String(value) === String(child.props.value || idx); return React.cloneElement(child, Object.assign(Object.assign({}, child.props), { className: classNames(child.props.className, isActive ? `${classPrefix}-content-active` : `${classPrefix}-content-inactive`), active: value === child.props.value, autoHeightClassName: autoHeight && String(value) !== String(child.props.value || idx) ? "inactive" : void 0 })); })) ) ); }; Tabs$1.displayName = "NutTabs"; Tabs$1.TabPane = TabPane; const Tabs = (props) => { const { items, fixWidth = false, className } = props, restProps = __rest(props, ["items", "fixWidth", "className"]); const cls = classNames(className, { "nut-tabs-fix-width": !!fixWidth }); if (items) { return React.createElement(Tabs$1, Object.assign({}, restProps), items.map((item) => { return React.createElement(Tabs$1.TabPane, { className: cls, key: item.key, value: item.key, title: React.createElement( React.Fragment, null, !!(item === null || item === void 0 ? void 0 : item.icon) && React.createElement("div", { className: "nut-tabs-titles-item-text-icon" }, item === null || item === void 0 ? void 0 : item.icon), item === null || item === void 0 ? void 0 : item.label ) }, item === null || item === void 0 ? void 0 : item.children); })); } return React.createElement(Tabs$1, Object.assign({}, restProps, { className: cls })); }; Tabs.TabPane = Tabs$1.TabPane; export { Tabs as T };