azure-devops-ui
Version:
React components for building web UI in Azure DevOps
97 lines (96 loc) • 6.71 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import "./ColorPicker.css";
import * as React from "react";
import { wait } from '../../Core/Util/Promise';
import { Button } from '../../Button';
import { Callout, ContentSize } from '../../Callout';
import { FocusZone, FocusZoneDirection, FocusZoneKeyStroke } from '../../FocusZone';
import { SimpleTableCell, Table } from '../../Table';
import { css, KeyCode } from '../../Util';
import { colorItems, colorRowProvider } from "./Utils";
export class ColorDropdownCalloutComponent extends React.Component {
constructor() {
super(...arguments);
this._focusedColumn = 0;
this.renderCell = (rowIndex, columnIndex, tableColumn, tableRow, ariaRowIndex) => {
var _a;
const cell = tableRow.cells[columnIndex];
const selectedIdx = (_a = this.props.selection) === null || _a === void 0 ? void 0 : _a.value[0].beginIndex;
const selected = cell === colorItems[selectedIdx !== null && selectedIdx !== void 0 ? selectedIdx : 0];
return (React.createElement(SimpleTableCell, { ariaRowIndex: ariaRowIndex, columnIndex: columnIndex, key: columnIndex, tableColumn: tableColumn },
React.createElement(Button, { id: `${rowIndex}-${columnIndex}`, className: css(selected && "bolt-dropdown-init-focus", "color-button flex-grow"), style: {
backgroundColor: "#" + cell.id
}, tooltipProps: { text: cell.text }, onClick: e => {
var _a;
const idx = colorItems.findIndex(ci => ci.id === cell.id);
if (idx >= 0) {
(_a = this.props.selection) === null || _a === void 0 ? void 0 : _a.select(idx);
this.props.onSelect && this.props.onSelect(e, colorItems[idx]);
this.props.onDismiss();
}
}, onFocus: () => (this._focusedColumn = columnIndex),
// hack to prevent <tr> from getting focused
onKeyDown: e => {
if (columnIndex === 0 && e.which === KeyCode.leftArrow) {
e.preventDefault();
}
} })));
};
this.columns = [
{ id: "c1", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c2", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c3", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c4", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c5", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c6", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c7", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c8", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c9", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c10", renderCell: this.renderCell, width: -100 / 11 },
{ id: "c11", renderCell: this.renderCell, width: -100 / 11 }
];
}
render() {
const { anchorElement, anchorOffset, anchorOrigin, anchorPoint, blurDismiss = true, calloutContentClassName, contentLocation, dropdownOrigin, excludeTabStop, id, lightDismiss, onFilterKeyDown } = this.props;
const focusOnMount = true;
const onDismiss = () => {
if (this.props.onDismiss) {
this.props.onDismiss();
}
};
return (React.createElement(Callout, { anchorElement: anchorElement, anchorOffset: anchorOffset, anchorOrigin: anchorOrigin, anchorPoint: anchorPoint, blurDismiss: blurDismiss, calloutOrigin: dropdownOrigin, contentClassName: css(calloutContentClassName, "bolt-dropdown flex-column custom-scrollbar v-scroll-auto h-scroll-hidden color-dropdown-callout"), contentLocation: contentLocation, contentShadow: true, contentSize: ContentSize.Auto, escDismiss: true, id: id, lightDismiss: lightDismiss, focuszoneProps: {
postprocessKeyStroke: event => {
// dismiss the callout on tab key instead of letting the
// browser handle the tab key, since with React.portals it
// will move to the body, instead of the next tabbable element after
// the dropdown.
if (event.which === KeyCode.tab && !event.defaultPrevented) {
event.preventDefault();
onDismiss();
return FocusZoneKeyStroke.IgnoreAll;
}
return FocusZoneKeyStroke.IgnoreNone;
}
}, onDismiss: onDismiss },
React.createElement(FocusZone, { circularNavigation: true, defaultActiveElement: ".bolt-dropdown-init-focus", direction: FocusZoneDirection.Vertical, focusOnMount: focusOnMount !== undefined ? focusOnMount : true },
React.createElement("div", { className: "bolt-dropdown-container no-outline", onKeyDown: onFilterKeyDown },
React.createElement("div", { "aria-hidden": "true", className: "no-outline", tabIndex: !excludeTabStop ? -1 : undefined, role: "listbox" }),
React.createElement(Table, { columns: this.columns, containerClassName: "color-dropdown-table-container", itemProvider: colorRowProvider, onFocus: async (reactEvent, r) => {
// when the table is focused, try to focus the correct button
const evt = reactEvent.nativeEvent;
// Sometimes FocusZone correctly focuses the right button. If we also focus it, that
// screws up FocusZone's counting. So we have to wait a sec and check to see if the
// button is already focused to avoid double focusing.
await wait(0);
if (evt.target.tagName === "TR") {
const row = evt.target;
// tslint:disable-next-line: no-unnecessary-type-assertion the type assertion is necessary, tslint
const button = row.querySelector(`td[data-column-index="${this._focusedColumn}"] button`);
if (button && button !== document.activeElement) {
button.focus();
}
}
} })))));
}
}