UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

92 lines (91 loc) 6.24 kB
import "../../CommonImports"; import "../../Core/core.css"; import "./SuggestionsList.css"; import * as React from "react"; import { ObservableLike } from '../../Core/Observable'; import { FocusWithin } from '../../FocusWithin'; import { Observer } from '../../Observer'; import { Spinner } from '../../Spinner'; import { css, getSafeId, preventDefault } from '../../Util'; export class SuggestionsItem extends React.Component { constructor() { super(...arguments); this.onSuggestionClicked = (ev) => { if (!ev.isDefaultPrevented()) { this.props.onClick(this.props); ev.preventDefault(); } }; } render() { const { renderSuggestion, className, isSelected } = this.props; return (React.createElement("div", { className: css(className, "bolt-suggestions-item flex-row flex-grow cursor-pointer scroll-hidden", isSelected && "bolt-suggestions-isSuggested"), onPointerDown: preventDefault }, React.createElement("div", { onMouseDown: preventDefault, onClick: this.onSuggestionClicked, className: "bolt-suggestions-item-button flex-row flex-grow scroll-hidden" }, renderSuggestion(this.props)))); } } export class SuggestionsList extends React.Component { constructor() { super(...arguments); this.scrollableRegion = React.createRef(); this.selectedElement = React.createRef(); this.onBlur = () => { this.props.onBlur && this.props.onBlur(); }; this.onFocus = (event) => { this.props.onFocus && this.props.onFocus(event); }; } render() { const { className, loadingText, renderNoResultFound } = this.props; const suggestions = ObservableLike.getValue(this.props.suggestions); const isLoading = ObservableLike.getValue(this.props.isLoading); // MostRecently Used text should supercede the header text if it's there and available. const hasNoSuggestions = (!suggestions || !suggestions.length) && !isLoading; return (React.createElement("div", { className: css(className, "bolt-suggestions flex-row flex-grow"), id: getSafeId("suggestions-list"), style: this.props.width ? { width: this.props.width } : undefined, onMouseDown: preventDefault }, isLoading ? (React.createElement(Spinner, { className: "bolt-suggestions-spinner flex-grow flex-center justify-center", id: "suggestions-spinner", label: loadingText })) : (!hasNoSuggestions && this.renderSuggestions()), React.createElement("div", { className: css("bolt-suggestions-none-region", !hasNoSuggestions ? "has-suggestions" : "flex-row flex-grow"), id: getSafeId("sug-list-no-results"), role: "alert" }, hasNoSuggestions && (renderNoResultFound ? renderNoResultFound() : this.noResults())), React.createElement("div", { "aria-label": loadingText || "Loading", id: getSafeId("sug-list-transition"), role: "text" }))); } componentDidMount() { this.scrollSelected(); } componentDidUpdate() { // Scroll to selected element only in case if selected element changed. // Otherwise mouse scroll won't work as it doesn't change selected element. if (this.selectedElement.current && this.currentSelectedElement !== this.selectedElement.current) { this.scrollSelected(); } } noResults() { const { noResultsFoundText } = this.props; return noResultsFoundText ? React.createElement("div", { className: "bolt-suggestions-none flex-row flex-grow flex-center" }, noResultsFoundText) : null; } renderSuggestions() { const { createDefaultItem, renderSuggestion, onSuggestionClicked, suggestionsItemClassName, resultsMaximumNumber, selectedIndex, suggestions, suggestionsContainerAriaLabel, width } = this.props; return (React.createElement(FocusWithin, { onBlur: this.onBlur, onFocus: this.onFocus }, (focusStatus) => { return (React.createElement(Observer, { suggestions: suggestions, selectedIndex: selectedIndex }, (props) => { if (resultsMaximumNumber) { props.suggestions = props.suggestions.slice(0, resultsMaximumNumber); } const sugList = props.suggestions; createDefaultItem && sugList.unshift(createDefaultItem(sugList)); return (React.createElement("div", { "aria-label": suggestionsContainerAriaLabel, className: "bolt-suggestions-container flex-column flex-grow v-scroll-auto h-scroll-hidden", id: getSafeId("suggestion-list"), ref: this.scrollableRegion, role: "listbox", style: width ? { width: width } : undefined }, React.createElement("div", { className: "bolt-suggestion-spacer", onMouseDown: preventDefault }), props.suggestions.map((suggestion, index) => { const isSuggested = index === props.selectedIndex; return (React.createElement("div", { className: "flex-noshrink", key: getSafeId("sug-" + index), id: getSafeId("sug-row-" + index), ref: isSuggested ? this.selectedElement : "", role: "option" }, React.createElement(SuggestionsItem, { className: suggestionsItemClassName, id: getSafeId("sug-item" + index), index: index, isSelected: isSuggested, item: suggestion, onBlur: focusStatus.onBlur, onFocus: focusStatus.onFocus, onClick: onSuggestionClicked, renderSuggestion: renderSuggestion }))); }), React.createElement("div", { className: "bolt-suggestion-spacer", onMouseDown: preventDefault }))); })); })); } scrollSelected() { var _a, _b; this.currentSelectedElement = (_a = this.selectedElement) === null || _a === void 0 ? void 0 : _a.current; if (this.scrollableRegion.current && ((_b = this.selectedElement) === null || _b === void 0 ? void 0 : _b.current)) { // IE11 messes up when scrollIntoView is called in the callout. this.scrollableRegion.current.scrollTop = this.selectedElement.current.offsetTop; } } }