azure-devops-ui
Version:
React components for building web UI in Azure DevOps
88 lines (87 loc) • 5.27 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import "./Table.css";
import { ObservableValue } from '../../Core/Observable';
import { ExpandableButton } from '../../Button';
import { ContextualMenu } from '../../Menu';
import * as Resources from '../../Resources.Widgets';
import { KeyCode, css, eventTargetContainsNode, preventDefault } from '../../Util';
import { Location } from '../../Utilities/Position';
import * as React from "react";
import { IMeasurementStyle, TableColumnLayout } from "./Table.Props";
/**
* Standard widths for the more column
*/
export var ColumnMoreWidths;
(function (ColumnMoreWidths) {
ColumnMoreWidths[ColumnMoreWidths["compact"] = 2] = "compact";
ColumnMoreWidths[ColumnMoreWidths["default"] = 2.625] = "default";
})(ColumnMoreWidths || (ColumnMoreWidths = {}));
/**
* The ColumnMore class is used as a custom column within a Table.
*
* It renders a fixed width column with a button that is visible on focus and
* hover that will show a contextual menu for the given item. The caller
* should create a new instance of this for each table. The header for this
* column is empty.
*
* When creating the column you must supply delegate that is used to get the
* menuProps when the menu is opened.
*/
export class ColumnMore {
/**
* Creates an instance of ColumnMore with the appropriate delegates.
*
* @param menuProvider Method that returns the menu props. This is called
* with the item from the row the menu was activated on.
* @param menuAvailable Optional method that is called when the row
* is rendered. The MoreButton will be shown if no method is supplied
* or if the method is supplied and it returns true.
*/
constructor(menuProvider, menuAvailable, onActivate, width = ColumnMoreWidths.default, refs) {
this.ariaLabel = Resources.MoreActions;
this.columnLayout = TableColumnLayout.none;
this.id = "_more";
this.widthStyle = IMeasurementStyle.REM;
this.renderCell = (rowIndex, columnIndex, tableColumn, listItem) => {
var _a;
const buttonRef = React.createRef();
if (this.refs && !this.refs.value[rowIndex]) {
this.refs.value[rowIndex] = buttonRef;
}
return (React.createElement("td", { "aria-colindex": columnIndex + 1, className: css("bolt-table-cell-side-action bolt-table-cell bolt-list-cell", "col-" + columnIndex), "data-column-index": columnIndex, key: "col-more", onClick: this.onClick, onDoubleClick: preventDefault, onKeyDown: this.onKeyDown, onMouseDown: preventDefault }, !this.menuAvailable || this.menuAvailable(listItem) ? (React.createElement("div", { className: "bolt-table-cell-content-reveal flex-row justify-center" },
React.createElement(ExpandableButton, { ariaLabel: Resources.MoreTooltip, className: "bolt-table-button-more", excludeTabStop: true, hideDropdownIcon: true, iconProps: { className: "small", iconName: "MoreVertical" }, onClick: e => {
if (this.onActivate) {
this.onActivate(rowIndex, columnIndex, e);
}
}, ref: (_a = this.refs) === null || _a === void 0 ? void 0 : _a.value[rowIndex], renderCallout: (dropdown, dropdownId, anchorElement) => {
return (React.createElement(ContextualMenu, { anchorElement: anchorElement, anchorOrigin: { horizontal: Location.end, vertical: Location.end }, menuProps: Object.assign(Object.assign({}, this.menuProvider(listItem, rowIndex, buttonRef)), { id: dropdownId }), menuOrigin: { horizontal: Location.end, vertical: Location.start }, onDismiss: dropdown.collapse }));
}, subtle: true, tooltipProps: { text: Resources.MoreTooltip } }))) : (React.createElement("span", { className: "bolt-table-cell-content visually-hidden" }, Resources.NoMoreActions))));
};
this.renderHeaderCell = (columnIndex, tableColumn) => {
return (React.createElement("th", { "aria-colindex": columnIndex + 1, "aria-label": tableColumn.ariaLabel, className: css(tableColumn.headerClassName, "bolt-table-header-cell", "col-header-" + columnIndex), "data-column-index": columnIndex, key: "col-more" },
React.createElement("span", { className: "visually-hidden" }, tableColumn.ariaLabel)));
};
this.onClick = (event) => {
if (!event.defaultPrevented) {
if (!eventTargetContainsNode(event, ["A"], document.body)) {
event.preventDefault();
}
}
};
this.onKeyDown = (event) => {
if (!event.defaultPrevented) {
if (event.which === KeyCode.enter || event.which === KeyCode.space) {
if (!eventTargetContainsNode(event, ["A"])) {
event.preventDefault();
}
}
}
};
this.menuAvailable = menuAvailable;
this.menuProvider = menuProvider;
this.onActivate = onActivate;
this.width = new ObservableValue(width);
this.refs = refs;
}
}