azure-devops-ui
Version:
React components for building web UI in Azure DevOps
99 lines (98 loc) • 5.92 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import "./Autocomplete.css";
import * as React from "react";
import * as Resources from '../../Resources.Label';
import { css, getSafeId } from '../../Util';
import { Spinner, SpinnerSize } from '../../Spinner';
import { Label } from "../Label/Label";
import { ColorPip, ColorSwatchPicker } from '../../Color';
import { Icon } from '../../Icon';
export class Suggestions extends React.Component {
constructor(props) {
super(props);
this.currentSelectedElementRef = React.createRef();
this.onHoverNewRowEnd = () => {
this.setState({
isNewRowHovered: false
});
};
this.onHoverNewRowStart = () => {
this.setState({
isNewRowHovered: true
});
};
this.onRenderAlreadyIncludedRow = () => {
const { inputAlreadyInGroupText = Resources.LabelInGroup } = this.props;
return (React.createElement("div", { className: "bolt-label-suggestions-row flex-row", key: "included" },
React.createElement(Icon, { className: "bolt-label-suggestions-icon", iconName: "CheckMark" }),
React.createElement("div", { className: "bolt-label-suggestions-row--content" }, inputAlreadyInGroupText)));
};
this.onRenderLoadingRow = () => {
return (React.createElement("div", { className: "bolt-label-suggestions-loading-row", key: "loading" },
React.createElement(Spinner, { size: SpinnerSize.small, label: Resources.LoadingSuggestions })));
};
this.onRenderNewLabelRow = (colors) => {
let content;
if (this.shouldDisplayColorPicker()) {
content = (React.createElement(ColorSwatchPicker, { className: css(this.isNewRowSelected() && "selected"), colors: colors, onPipClick: this.props.onColorPipClick, selectedIndex: this.props.currentSelectedColorIndex }));
}
else {
content = (React.createElement("div", { className: css("bolt-label-suggestions-row clickable flex-row", this.isNewRowSelected() && "selected"), onClick: this.props.onNewLabelClick, role: "option", tabIndex: -1 },
React.createElement(ColorPip, { color: this.props.disableColorPicker && Label.DEFAULT_COLOR }),
React.createElement("div", { className: "bolt-label-suggestions-row--content" }, Resources.NewLabelSuggestionText)));
}
return (React.createElement("div", { className: "bolt-label-suggestions-newRow-wrapper", key: "newRow", onMouseEnter: this.onHoverNewRowStart, onMouseLeave: this.onHoverNewRowEnd }, content));
};
this.onRenderSuggestionRow = (labelModel, index) => {
const isSelected = this.props.currentSelectedIndex === index;
return (React.createElement("div", { "aria-selected": isSelected, className: css("bolt-label-suggestions-row clickable flex-row", isSelected && "selected"), id: getSafeId(labelModel.content), key: labelModel.content, onClick: (event) => this.props.onSuggestionClick(event, labelModel), ref: isSelected && this.currentSelectedElementRef, role: "option", tabIndex: -1 },
React.createElement(ColorPip, { color: labelModel.color }),
React.createElement("div", { className: "bolt-label-suggestions-row--content" },
React.createElement("span", null, labelModel.content))));
};
this.state = {
isNewRowHovered: false
};
}
render() {
const { isCurrentInputAlreadyInGroup, isLoading, onCheckForExactMatch, suggestedItems, swatchPickerColors } = this.props;
const minWidth = swatchPickerColors.length * 32;
// Determine items to render
const calloutItems = [];
const renderLoadingRow = isLoading;
const renderIncludedRow = isCurrentInputAlreadyInGroup;
const renderNewLabelRow = !renderIncludedRow && (onCheckForExactMatch === undefined || !onCheckForExactMatch(suggestedItems));
if (renderLoadingRow) {
calloutItems.push(this.onRenderLoadingRow());
}
suggestedItems.length > 0 &&
calloutItems.push(React.createElement("div", { className: "bolt-label-suggestions-list", key: "suggestions" }, suggestedItems.map(this.onRenderSuggestionRow)));
if (renderIncludedRow) {
calloutItems.push(this.onRenderAlreadyIncludedRow());
}
if (renderNewLabelRow) {
calloutItems.push(this.onRenderNewLabelRow(swatchPickerColors));
}
// Interleave separators as necessary
const calloutContents = [];
calloutItems.forEach((element, index) => {
index !== 0 && calloutContents.push(React.createElement("div", { className: "bolt-suggestions-separator", key: "separator" + index }));
calloutContents.push(element);
});
return (React.createElement("div", { className: "bolt-label-suggestions-container flex-column", id: getSafeId("autocomplete-listbox"), role: "listbox", style: { minWidth: minWidth } }, calloutContents));
}
componentDidUpdate() {
if (this.currentSelectedElementRef.current && this.currentSelectedElementRef.current !== this.previousSelectedElement) {
this.currentSelectedElementRef.current.scrollIntoView(false);
this.previousSelectedElement = this.currentSelectedElementRef.current;
}
}
isNewRowSelected() {
return this.props.currentSelectedIndex === this.props.suggestedItems.length;
}
shouldDisplayColorPicker() {
const { disableColorPicker = false } = this.props;
return !disableColorPicker && (this.isNewRowSelected() || this.state.isNewRowHovered);
}
}