azure-devops-ui
Version:
React components for building web UI in Azure DevOps
107 lines (106 loc) • 5.06 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import "./Tabs.css";
import * as React from "react";
import { FocusGroupContext } from '../../FocusGroup';
import { FocusZoneContext } from '../../FocusZone';
import { Icon } from '../../Icon';
import { Observer } from '../../Observer';
import { Tooltip } from '../../TooltipEx';
import { css, getSafeId, KeyCode } from '../../Util';
import { getFriendlyDisplayValue } from '../../Utilities/FriendlyNumber';
import { TabBadge } from "./TabBadge";
/**
* Presentational component that represents a single tab.
*/
export class Tab extends React.Component {
constructor() {
super(...arguments);
this.onClick = (event) => {
const { url } = this.props;
let updatePivot = true;
// If ctrl-click is pressed, and there is a URL specified for this item, then
// don't handle the click here, allowing the browser to perform a navigation
// (i.e. open in a new tab/window)
if (event.ctrlKey) {
if (url) {
updatePivot = false;
}
}
if (updatePivot) {
event.preventDefault();
this.updateSelectedItem(event);
}
};
this.onKeyDown = (event) => {
if (!event.defaultPrevented) {
if (event.which === KeyCode.space || event.which === KeyCode.enter) {
event.preventDefault();
this.updateSelectedItem(event);
}
}
};
}
render() {
const { ariaLabel, index, setSize, iconProps, id, isSelected, renderBadge, url } = this.props;
const TagName = url ? "a" : "div";
return (React.createElement(Observer, { name: this.props.name, badgeCount: this.props.badgeCount }, (props) => {
const name = props.name;
return (React.createElement(FocusGroupContext.Consumer, null, focusGroupContext => (React.createElement(FocusZoneContext.Consumer, null, zoneContext => {
const badge = renderBadge ? renderBadge() : this.renderBadge(props.badgeCount);
const icon = iconProps !== undefined && Icon(Object.assign({ className: "bolt-tab-icon" }, iconProps));
const text = name && (React.createElement("span", { className: "bolt-tab-text", "data-content": name }, name));
const tooltipProps = icon && !name && ariaLabel
? {
text: ariaLabel,
overflowOnly: false
}
: {
text: name,
overflowDetected,
overflowOnly: true
};
return (React.createElement(Tooltip, Object.assign({}, tooltipProps),
React.createElement(TagName, { "aria-label": ariaLabel, "aria-posinset": index !== undefined ? index + 1 : undefined, "aria-selected": isSelected, "aria-setsize": setSize, className: css(this.props.className, "bolt-tab focus-treatment flex-noshrink", isSelected && "selected"), "data-focuszone": zoneContext.focuszoneId, href: url, id: getSafeId("tab-" + id), key: id, onClick: this.onClick, onKeyDown: this.onKeyDown, role: "tab", tabIndex: focusGroupContext.focusedElementId === "tab-" + id ? 0 : -1, onFocus: this.props.onFocus },
React.createElement("span", { className: "bolt-tab-inner-container" },
icon,
text,
badge))));
}))));
}));
}
renderBadge(badgeCount) {
const badgeDisplayValue = badgeCount !== undefined ? getFriendlyDisplayValue(badgeCount) : undefined;
let badgeTooltip = undefined;
if (badgeCount && badgeDisplayValue !== badgeCount.toString()) {
badgeTooltip = badgeCount.toString();
}
let badge = null;
if (badgeDisplayValue) {
const tooltipProps = badgeTooltip ? { text: badgeTooltip } : undefined;
badge = React.createElement(TabBadge, { tooltipProps: tooltipProps }, badgeDisplayValue);
}
return badge;
}
/**
* Updates the state with the new selected pivot.
*/
updateSelectedItem(ev) {
const { onClick } = this.props;
if (ev && this.props.onBeforeTabChange && !this.props.onBeforeTabChange(ev, this.props.id, this.props.url)) {
ev.preventDefault();
return;
}
// Update notifiers
if (onClick) {
onClick(this.props.id);
}
}
}
function overflowDetected(anchorElement) {
const overflowElement = anchorElement.querySelector(".bolt-tab-text");
if (overflowElement) {
return overflowElement && overflowElement.scrollWidth > Math.ceil(overflowElement.offsetWidth);
}
return false;
}