@douyinfe/semi-ui
Version:
A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.
354 lines (353 loc) • 13.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _exportNames = {};
exports.default = void 0;
var _pick2 = _interopRequireDefault(require("lodash/pick"));
var _isEqual2 = _interopRequireDefault(require("lodash/isEqual"));
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _constants = require("@douyinfe/semi-foundation/lib/cjs/tabs/constants");
var _isNullOrUndefined = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/utils/isNullOrUndefined"));
var _foundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/tabs/foundation"));
var _baseComponent = _interopRequireDefault(require("../_base/baseComponent"));
require("@douyinfe/semi-foundation/lib/cjs/tabs/tabs.css");
var _TabBar = _interopRequireDefault(require("./TabBar"));
var _TabPane = _interopRequireDefault(require("./TabPane"));
var _TabItem = _interopRequireDefault(require("./TabItem"));
var _tabsContext = _interopRequireDefault(require("./tabs-context"));
var _utils = require("../_utils");
var _interface = require("./interface");
Object.keys(_interface).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _interface[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _interface[key];
}
});
});
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var __rest = void 0 && (void 0).__rest || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
};
const panePickKeys = ['className', 'style', 'disabled', 'itemKey', 'tab', 'icon'];
class Tabs extends _baseComponent.default {
constructor(props) {
super(props);
this.setContentRef = ref => {
this.contentRef = {
current: ref
};
};
this.getPanes = () => {
const {
tabList,
children
} = this.props;
if (Array.isArray(tabList) && tabList.length) {
return tabList;
}
return _react.default.Children.map(children, child => {
if (child) {
const {
tab,
icon,
disabled,
itemKey,
closable
} = child.props;
return {
tab,
icon,
disabled,
itemKey,
closable
};
}
return undefined;
});
};
this.onTabClick = (activeKey, event) => {
this.foundation.handleTabClick(activeKey, event);
};
/* istanbul ignore next */
this.rePosChildren = (children, activeKey) => {
const newChildren = [];
const falttenChildren = _react.default.Children.toArray(children);
if (children.length) {
newChildren.push(...falttenChildren.filter(child => child.props && child.props.itemKey === activeKey));
newChildren.push(...falttenChildren.filter(child => child.props && child.props.itemKey !== activeKey));
}
return newChildren;
};
this.getActiveItem = () => {
const {
activeKey
} = this.state;
const {
children,
tabList
} = this.props;
if (tabList || !Array.isArray(children)) {
return children;
}
return _react.default.Children.toArray(children).filter(pane => {
if ( /*#__PURE__*/(0, _react.isValidElement)(pane) && pane.type && pane.type.isTabPane) {
return pane.props.itemKey === activeKey;
}
return true;
});
};
this.deleteTabItem = (tabKey, event) => {
event.stopPropagation();
this.foundation.handleTabDelete(tabKey);
};
this.foundation = new _foundation.default(this.adapter);
this.state = {
activeKey: this.foundation.getDefaultActiveKey(),
panes: this.getPanes(),
prevActiveKey: null,
forceDisableMotion: false
};
this.contentRef = /*#__PURE__*/(0, _react.createRef)();
this.contentHeight = 'auto';
}
get adapter() {
return Object.assign(Object.assign({}, super.adapter), {
collectPane: () => {
const panes = this.getPanes();
this.setState({
panes
});
},
collectActiveKey: () => {
const {
tabList,
children,
activeKey: propsActiveKey
} = this.props;
if (typeof propsActiveKey !== 'undefined') {
return;
}
const {
activeKey
} = this.state;
const panes = this.getPanes();
if (panes.findIndex(p => p.itemKey === activeKey) === -1) {
if (panes.length > 0) {
this.setState({
activeKey: panes[0].itemKey
});
} else {
this.setState({
activeKey: ''
});
}
}
},
notifyTabClick: (activeKey, event) => {
this.props.onTabClick(activeKey, event);
},
notifyChange: activeKey => {
this.props.onChange(activeKey);
},
setNewActiveKey: activeKey => {
this.setState({
activeKey
});
},
getDefaultActiveKeyFromChildren: () => {
const {
tabList,
children
} = this.props;
let activeKey = '';
const list = tabList ? tabList : _react.default.Children.toArray(children).map(child => /*#__PURE__*/(0, _react.isValidElement)(child) ? child.props : null);
list.forEach(item => {
if (item && !activeKey && !item.disabled) {
activeKey = item.itemKey;
}
});
return activeKey;
},
notifyTabDelete: tabKey => {
this.props.onTabClose && this.props.onTabClose(tabKey);
}
});
}
static getDerivedStateFromProps(props, state) {
const states = {};
if (!(0, _isNullOrUndefined.default)(props.activeKey) && props.activeKey !== state.activeKey) {
state.prevActiveKey = state.activeKey;
states.activeKey = props.activeKey;
}
return states;
}
componentDidUpdate(prevProps, prevState) {
// Panes state acts on tab bar, no need to compare TabPane children
const prevChildrenProps = _react.default.Children.toArray(prevProps.children).map(child => (0, _pick2.default)( /*#__PURE__*/(0, _react.isValidElement)(child) ? child.props : null, panePickKeys));
const nowChildrenProps = _react.default.Children.toArray(this.props.children).map(child => (0, _pick2.default)( /*#__PURE__*/(0, _react.isValidElement)(child) ? child.props : null, panePickKeys));
const isTabListType = this.props.tabList || prevProps.tabList;
if (!(0, _isEqual2.default)(this.props.tabList, prevProps.tabList)) {
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
// children changed: recalc activeKey. TabPane could be updated async. If not recalc the first panel will not be activated
if (!(0, _isEqual2.default)(prevChildrenProps, nowChildrenProps) && !isTabListType) {
this.foundation.handleTabPanesChange();
}
}
render() {
const _a = this.props,
{
children,
className,
collapsible,
contentStyle,
keepDOM,
lazyRender,
renderTabBar,
showRestInDropdown,
size,
style,
tabBarClassName,
tabBarExtraContent,
tabBarStyle,
tabPaneMotion,
tabPosition,
type,
more,
onVisibleTabsChange,
visibleTabsStyle,
arrowPosition,
renderArrow
} = _a,
restProps = __rest(_a, ["children", "className", "collapsible", "contentStyle", "keepDOM", "lazyRender", "renderTabBar", "showRestInDropdown", "size", "style", "tabBarClassName", "tabBarExtraContent", "tabBarStyle", "tabPaneMotion", "tabPosition", "type", "more", "onVisibleTabsChange", "visibleTabsStyle", "arrowPosition", "renderArrow"]);
const {
panes,
activeKey
} = this.state;
const tabWrapperCls = (0, _classnames.default)(className, {
[_constants.cssClasses.TABS]: true,
[`${_constants.cssClasses.TABS}-${tabPosition}`]: tabPosition
});
const tabContentCls = (0, _classnames.default)({
[_constants.cssClasses.TABS_CONTENT]: true,
[`${_constants.cssClasses.TABS_CONTENT}-${tabPosition}`]: tabPosition
});
const tabBarProps = {
activeKey,
className: tabBarClassName,
collapsible,
list: panes,
onTabClick: this.onTabClick,
showRestInDropdown,
size,
style: tabBarStyle,
tabBarExtraContent,
tabPosition,
type,
deleteTabItem: this.deleteTabItem,
handleKeyDown: this.foundation.handleKeyDown,
more,
onVisibleTabsChange,
visibleTabsStyle,
arrowPosition,
renderArrow
};
const tabBar = renderTabBar ? renderTabBar(tabBarProps, _TabBar.default) : /*#__PURE__*/_react.default.createElement(_TabBar.default, Object.assign({}, tabBarProps));
const content = keepDOM ? children : this.getActiveItem();
return /*#__PURE__*/_react.default.createElement("div", Object.assign({
className: tabWrapperCls,
style: style
}, this.getDataAttr(restProps)), tabBar, /*#__PURE__*/_react.default.createElement(_tabsContext.default.Provider, {
value: {
activeKey,
lazyRender,
panes,
tabPaneMotion,
tabPosition,
prevActiveKey: this.state.prevActiveKey,
forceDisableMotion: this.state.forceDisableMotion
}
}, /*#__PURE__*/_react.default.createElement("div", {
ref: this.setContentRef,
className: tabContentCls,
style: Object.assign({}, contentStyle)
}, content)));
}
}
Tabs.TabPane = _TabPane.default;
Tabs.TabItem = _TabItem.default;
Tabs.propTypes = {
activeKey: _propTypes.default.string,
className: _propTypes.default.string,
collapsible: _propTypes.default.bool,
contentStyle: _propTypes.default.oneOfType([_propTypes.default.object]),
defaultActiveKey: _propTypes.default.string,
keepDOM: _propTypes.default.bool,
lazyRender: _propTypes.default.bool,
onChange: _propTypes.default.func,
onTabClick: _propTypes.default.func,
renderTabBar: _propTypes.default.func,
showRestInDropdown: _propTypes.default.bool,
size: _propTypes.default.oneOf(_constants.strings.SIZE),
style: _propTypes.default.object,
tabBarClassName: _propTypes.default.string,
tabBarExtraContent: _propTypes.default.node,
tabBarStyle: _propTypes.default.object,
tabList: _propTypes.default.array,
tabPaneMotion: _propTypes.default.bool,
tabPosition: _propTypes.default.oneOf(_constants.strings.POSITION_MAP),
type: _propTypes.default.oneOf(_constants.strings.TYPE_MAP),
onTabClose: _propTypes.default.func,
preventScroll: _propTypes.default.bool,
more: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.object]),
arrowPosition: _propTypes.default.string,
renderArrow: _propTypes.default.func
};
Tabs.__SemiComponentName__ = "Tabs";
Tabs.defaultProps = (0, _utils.getDefaultPropsFromGlobalConfig)(Tabs.__SemiComponentName__, {
children: [],
collapsible: false,
keepDOM: true,
lazyRender: false,
onChange: () => undefined,
onTabClick: () => undefined,
size: 'large',
tabPaneMotion: true,
tabPosition: 'top',
type: 'line',
onTabClose: () => undefined,
showRestInDropdown: true,
arrowPosition: "both"
});
var _default = exports.default = Tabs;