@talend/react-components
Version:
Set of react components.
225 lines (222 loc) • 7.34 kB
JavaScript
/* eslint-disable react/jsx-no-bind */
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable react/no-find-dom-node */
import { useEffect, useRef, useState, createElement as _createElement } from 'react';
import ReactDOM from 'react-dom';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { Nav, NavItem, Tab } from '@talend/react-bootstrap';
import { ActionDropdown } from '../Actions';
import Icon from '../Icon';
import OverlayTrigger from '../OverlayTrigger';
import Tag from '../Tag';
import TooltipTrigger from '../TooltipTrigger';
import getTabBarBadgeLabel from '../utils/getTabBarBadgeLabel';
import theme from './TabBar.module.scss';
import { debounce, get } from "lodash";
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
function TabBar(props) {
const tabBarContainerRef = useRef();
const tabBarRef = useRef();
const needsRefocus = useRef();
const [showDropdown, setShowDropDown] = useState(false);
const {
responsive = true
} = props;
function tryShowDropdown() {
const tabContainer = tabBarContainerRef.current;
if (tabContainer) {
// There is a TabBar, test if the right boundary point of this TabBar
// is closer than the right boundary point of its last nav item.
const lastChild = tabContainer.querySelector('li:last-child');
if (lastChild) {
if (tabContainer.getBoundingClientRect().right < lastChild.getBoundingClientRect().right) {
setShowDropDown(true);
}
}
} else {
// There is no TabBar, show it to test if dropdown is needed
setShowDropDown(false);
}
}
/**
* Just show the tabBar and test if there is enough width.
*/
function showTabBarAndTest() {
setShowDropDown(false);
tryShowDropdown();
}
useEffect(() => {
if (responsive) {
const resizeListener = window.addEventListener('resize', debounce(showTabBarAndTest, 200));
return () => window.removeEventListener('resize', resizeListener);
}
return undefined;
}, []);
useEffect(() => {
if (!needsRefocus.current || !tabBarRef.current) {
return;
}
const tabBarRefNode = ReactDOM.findDOMNode(tabBarRef.current);
if (tabBarRefNode && typeof tabBarRefNode.querySelector === 'function') {
const activeChild = tabBarRefNode.querySelector('[aria-selected=true]');
if (activeChild) {
activeChild.focus({
preventScroll: true
});
needsRefocus.current = false;
}
}
});
useEffect(() => {
if (responsive) {
tryShowDropdown();
}
}, []);
const {
onSelect
} = props; // to avoid react/no-unused-prop-types
function handleSelect(selectedKey, event) {
if (selectedKey !== props.selectedKey) {
if (event) {
event.preventDefault();
}
onSelect(event, props.items.find(({
key
}) => selectedKey === key));
}
}
function handleKeyDown(event) {
const {
items
} = props;
switch (event.key) {
case 'Home':
needsRefocus.current = true;
handleSelect(items[0].key, event);
break;
case 'End':
needsRefocus.current = true;
handleSelect(items[items.length - 1].key, event);
break;
default:
break;
}
}
const {
className,
id,
items,
selectedKey,
children,
generateChildId,
tooltipPlacement,
right
} = props;
const hasChildren = children || items.some(item => item.children);
const tabContent = hasChildren && /*#__PURE__*/_jsx(Tab.Content, {
children: items.map(item => /*#__PURE__*/_jsxs(Tab.Pane, {
eventKey: item.key,
children: [item.children, selectedKey === item.key ? children : null]
}, item.key))
});
let tabMenu;
if (responsive && showDropdown) {
const selectedItem = items.find(item => item.key === selectedKey) || items[0];
const badgeLabel = get(selectedItem, 'badge.label', '');
tabMenu = /*#__PURE__*/_jsx(ActionDropdown, {
id: id,
className: classnames(theme['tc-tab-bar-dropdown'], 'tc-tab-bar-dropdown'),
badge: selectedItem.badge,
tooltipLabel: badgeLabel ? `${badgeLabel} ${selectedItem.label}` : selectedItem.label,
label: selectedItem.label,
icon: selectedItem.icon && selectedItem.icon.name,
onSelect: (event, {
key
}) => handleSelect(key, event),
items: items.map(item => ({
...item,
icon: item.icon && item.icon.name
})),
link: true
});
} else {
tabMenu = /*#__PURE__*/_jsx(Nav, {
bsStyle: "tabs",
className: classnames(theme['tc-tab-bar'], 'tc-tab-bar', responsive && theme['tc-tab-bar-responsive'], responsive && 'tc-tab-bar-responsive'),
ref: tabBarRef,
children: items.map(({
icon,
badge,
...item
}) => /*#__PURE__*/_createElement(NavItem, {
className: classnames(theme['tc-tab-bar-item'], 'tc-tab-bar-item', item.className),
...item,
key: item.key,
eventKey: item.key,
componentClass: "button"
}, /*#__PURE__*/_jsx(TooltipTrigger, {
label: badge && badge.label ? `${badge.label} ${item.label}` : item.label,
tooltipPlacement: tooltipPlacement,
children: /*#__PURE__*/_jsxs("span", {
className: classnames(theme['tc-tab-bar-item-container'], 'tc-tab-bar-item-container'),
children: [icon && /*#__PURE__*/_jsx(Icon, {
className: classnames(theme['tc-tab-bar-item-icon'], 'tc-tab-bar-item-icon'),
...icon
}), /*#__PURE__*/_jsx("span", {
className: classnames(theme['tc-tab-bar-item-label']),
children: item.label
}), badge && /*#__PURE__*/_jsx(Tag, {
className: classnames(theme['tc-tab-bar-item-badge'], 'tc-tab-bar-item-badge', badge.className),
bsStyle: badge.bsStyle,
children: getTabBarBadgeLabel(badge.label)
})]
})
})))
});
}
return /*#__PURE__*/_jsx(Tab.Container, {
id: id,
activeKey: selectedKey,
className: className,
onSelect: handleSelect,
onKeyDown: handleKeyDown,
generateChildId: generateChildId,
children: /*#__PURE__*/_jsxs("div", {
ref: tabBarContainerRef,
children: [/*#__PURE__*/_jsxs("div", {
className: classnames(theme['tc-tab-bar-menu'], 'tc-tab-bar-menu'),
children: [tabMenu, right]
}), tabContent]
})
});
}
TabBar.displayName = 'TabBar';
TabBar.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
generateChildId: PropTypes.func,
id: PropTypes.string.isRequired,
items: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
key: PropTypes.any.isRequired,
label: PropTypes.string.isRequired,
icon: PropTypes.object,
badge: PropTypes.shape({
className: PropTypes.string,
label: PropTypes.string,
bsStyle: PropTypes.string
})
}).isRequired).isRequired,
onSelect: PropTypes.func.isRequired,
responsive: PropTypes.bool,
selectedKey: PropTypes.any,
tooltipPlacement: OverlayTrigger.propTypes.placement,
right: PropTypes.node
};
TabBar.defaultProps = {
tooltipPlacement: 'top'
};
TabBar.Tab = Tab;
export default TabBar;
//# sourceMappingURL=TabBar.component.js.map