|
|
@@ -1,19 +1,18 @@
|
|
|
-
|
|
|
-import React, { createRef, MouseEvent, ReactElement, ReactNode, RefCallback, RefObject, isValidElement } from 'react';
|
|
|
+import React, { createRef, isValidElement, MouseEvent, ReactElement, ReactNode, RefCallback, RefObject } from 'react';
|
|
|
import cls from 'classnames';
|
|
|
import PropTypes from 'prop-types';
|
|
|
import { cssClasses, strings } from '@douyinfe/semi-foundation/tabs/constants';
|
|
|
import isNullOrUndefined from '@douyinfe/semi-foundation/utils/isNullOrUndefined';
|
|
|
import getDataAttr from '@douyinfe/semi-foundation/utils/getDataAttr';
|
|
|
import TabsFoundation, { TabsAdapter } from '@douyinfe/semi-foundation/tabs/foundation';
|
|
|
-import { isEqual, pick, omit } from 'lodash';
|
|
|
+import { isEqual, pick } from 'lodash';
|
|
|
import BaseComponent from '../_base/baseComponent';
|
|
|
import '@douyinfe/semi-foundation/tabs/tabs.scss';
|
|
|
|
|
|
import TabBar from './TabBar';
|
|
|
import TabPane from './TabPane';
|
|
|
import TabsContext from './tabs-context';
|
|
|
-import { TabsProps, PlainTab, TabBarProps } from './interface';
|
|
|
+import { PlainTab, TabBarProps, TabsProps } from './interface';
|
|
|
|
|
|
const panePickKeys = ['className', 'style', 'disabled', 'itemKey', 'tab', 'icon'];
|
|
|
|
|
|
@@ -21,7 +20,9 @@ export * from './interface';
|
|
|
|
|
|
export interface TabsState {
|
|
|
activeKey: string;
|
|
|
- panes: Array<PlainTab>
|
|
|
+ panes: Array<PlainTab>;
|
|
|
+ prevActiveKey: string | null;
|
|
|
+ forceDisableMotion: boolean
|
|
|
}
|
|
|
|
|
|
class Tabs extends BaseComponent<TabsProps, TabsState> {
|
|
|
@@ -71,12 +72,12 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
|
|
|
|
|
|
constructor(props: TabsProps) {
|
|
|
super(props);
|
|
|
-
|
|
|
this.foundation = new TabsFoundation(this.adapter);
|
|
|
-
|
|
|
this.state = {
|
|
|
activeKey: this.foundation.getDefaultActiveKey(),
|
|
|
panes: [],
|
|
|
+ prevActiveKey: null,
|
|
|
+ forceDisableMotion: false
|
|
|
};
|
|
|
this.contentRef = createRef();
|
|
|
this.contentHeight = 'auto';
|
|
|
@@ -118,14 +119,14 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
|
|
|
return undefined;
|
|
|
});
|
|
|
}
|
|
|
- if (panes.findIndex(p => p.itemKey === activeKey) === -1){
|
|
|
- if (panes.length>0){
|
|
|
+ if (panes.findIndex(p => p.itemKey === activeKey) === -1) {
|
|
|
+ if (panes.length > 0) {
|
|
|
this.setState({ activeKey: panes[0].itemKey });
|
|
|
} else {
|
|
|
this.setState({ activeKey: '' });
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
},
|
|
|
notifyTabClick: (activeKey: string, event: MouseEvent<HTMLDivElement>): void => {
|
|
|
this.props.onTabClick(activeKey, event);
|
|
|
@@ -156,13 +157,14 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
|
|
|
static getDerivedStateFromProps(props: TabsProps, state: TabsState): Partial<TabsState> {
|
|
|
const states: Partial<TabsState> = {};
|
|
|
if (!isNullOrUndefined(props.activeKey) && props.activeKey !== state.activeKey) {
|
|
|
+ state.prevActiveKey = state.activeKey;
|
|
|
states.activeKey = props.activeKey;
|
|
|
}
|
|
|
return states;
|
|
|
}
|
|
|
|
|
|
|
|
|
- componentDidUpdate(prevProps: TabsProps): void {
|
|
|
+ componentDidUpdate(prevProps: TabsProps, prevState: TabsState): void {
|
|
|
// Panes state acts on tab bar, no need to compare TabPane children
|
|
|
const prevChildrenProps = React.Children.toArray(prevProps.children).map((child) =>
|
|
|
pick(isValidElement(child) ? child.props : null, panePickKeys)
|
|
|
@@ -177,6 +179,19 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
|
|
|
this.foundation.handleTabListChange();
|
|
|
}
|
|
|
|
|
|
+ if (prevState.activeKey !== this.state.activeKey && prevState.activeKey !== this.state.prevActiveKey) {
|
|
|
+ this.setState({ prevActiveKey: prevState.activeKey });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (prevProps.activeKey !== this.props.activeKey) {
|
|
|
+ const newAddedPanelItemKey = (() => {
|
|
|
+ const prevItemKeys = new Set(prevChildrenProps.map(p => p.itemKey));
|
|
|
+ return nowChildrenProps.map(p => p.itemKey).filter(itemKey => !prevItemKeys.has(itemKey));
|
|
|
+ })();
|
|
|
+ this.setState({ forceDisableMotion: newAddedPanelItemKey.includes(this.props.activeKey) });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
// children变化,tabList方式使用时,啥也不用做
|
|
|
// children变化,非tabList方式使用,需要重新取activeKey。TabPane可能是异步更新的,若不重新取,未设activeKey时,第一个不会自动激活
|
|
|
// children changed: do nothing in tabList case
|
|
|
@@ -285,6 +300,8 @@ class Tabs extends BaseComponent<TabsProps, TabsState> {
|
|
|
panes,
|
|
|
tabPaneMotion,
|
|
|
tabPosition,
|
|
|
+ prevActiveKey: this.state.prevActiveKey,
|
|
|
+ forceDisableMotion: this.state.forceDisableMotion
|
|
|
}}
|
|
|
>
|
|
|
<div
|