/** * @file Tabs * @description 选项卡 * @author fex */ import React from 'react'; import {Schema} from '../types'; import Transition, {ENTERED, ENTERING} from 'react-transition-group/Transition'; import {themeable, ThemeProps} from '../theme'; import {uncontrollable} from 'uncontrollable'; import {generateIcon} from '../utils/icon'; const transitionStyles: { [propName: string]: string; } = { [ENTERING]: 'in', [ENTERED]: 'in' }; export interface TabProps extends ThemeProps { title?: string; // 标题 icon?: string; iconPosition?: 'left' | 'right'; disabled?: boolean | string; eventKey: string | number; tab?: Schema; className?: string; activeKey?: string | number; reload?: boolean; mountOnEnter?: boolean; unmountOnExit?: boolean; toolbar?: React.ReactNode; } class TabComponent extends React.PureComponent { contentDom: any; contentRef = (ref: any) => (this.contentDom = ref); render() { const { classnames: cx, mountOnEnter, reload, unmountOnExit, eventKey, activeKey, children, className } = this.props; return ( {(status: string) => { if (status === ENTERING) { this.contentDom.offsetWidth; } return (
{children}
); }}
); } } export const Tab = themeable(TabComponent); export interface TabsProps extends ThemeProps { mode: '' | 'line' | 'card' | 'radio' | 'vertical' | 'chrome'; tabsMode?: '' | 'line' | 'card' | 'radio' | 'vertical' | 'chrome'; additionBtns?: React.ReactNode; onSelect?: (key: string | number) => void; activeKey?: string | number; contentClassName: string; className?: string; tabs?: Array; tabRender?: (tab: TabProps, props?: TabsProps) => JSX.Element; toolbar?: React.ReactNode; } export class Tabs extends React.Component { static defaultProps: Pick = { mode: '', contentClassName: '' }; static Tab = Tab; handleSelect(key: string | number) { const {onSelect} = this.props; onSelect && onSelect(key); } renderNav(child: any, index: number) { if (!child) { return; } const {classnames: cx, activeKey: activeKeyProp, mode} = this.props; const { eventKey, disabled, icon, iconPosition, title, toolbar } = child.props; const activeKey = activeKeyProp === undefined && index === 0 ? eventKey : activeKeyProp; const iconElement = generateIcon(cx, icon, 'Icon'); return (
  • (disabled ? '' : this.handleSelect(eventKey))} > {icon ? ( iconPosition === 'right' ? ( <> {title} {iconElement} ) : ( <> {iconElement} {title} ) ) : ( title )} {React.isValidElement(toolbar) ? toolbar : null} {/* svg 来自 https://github.com/adamschwartz/chrome-tabs */} {mode === 'chrome' ? (
    ) : null}
  • ); } renderTab(child: any, index: number) { if (!child) { return; } const {activeKey: activeKeyProp, classnames} = this.props; const eventKey = child.props.eventKey; const activeKey = activeKeyProp === undefined && index === 0 ? eventKey : activeKeyProp; return React.cloneElement(child, { ...child.props, key: index, classnames: classnames, activeKey: activeKey }); } render() { const { classnames: cx, contentClassName, className, mode: dMode, tabsMode, children, additionBtns, toolbar } = this.props; if (!Array.isArray(children)) { return null; } const mode = tabsMode || dMode; return (
      {children.map((tab, index) => this.renderNav(tab, index))} {additionBtns} {toolbar}
    {children.map((child, index) => { return this.renderTab(child, index); })}
    ); } } const ThemedTabs = themeable( uncontrollable(Tabs, { activeKey: 'onSelect' }) ); export default ThemedTabs as typeof ThemedTabs & { Tab: typeof Tab; };