UNPKG

@itwin/core-react

Version:

A react component library of iTwin.js UI general purpose components

171 lines 8.07 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module AutoSuggest */ import "./AutoSuggest.scss"; import * as React from "react"; import { Logger } from "@itwin/core-bentley"; import { Input } from "@itwin/itwinui-react"; import ReactAutosuggest from "react-autosuggest"; import { Key } from "ts-key-enum"; import { UiCore } from "../UiCore.js"; /** Auto Suggest React component. Uses the react-autosuggest component internally. * @public * @deprecated in 4.16.0. Use {@link https://itwinui.bentley.com/ iTwinUI components} instead. */ export class AutoSuggest extends React.PureComponent { _isMounted = false; constructor(props) { super(props); // Autosuggest is a controlled component. // This means that you need to provide an input value // and an onChange handler that updates this value (see below). // Suggestions also need to be provided to the Autosuggest, // and they are initially empty because the Autosuggest is closed. this.state = { inputValue: this.getLabel(props.value), suggestions: [], }; } componentDidMount() { this._isMounted = true; } componentWillUnmount() { this._isMounted = false; } /** @internal */ componentDidUpdate(prevProps) { if (this.props.value !== prevProps.value || this.props.options !== prevProps.options) { this.setState((_prevState, props) => ({ inputValue: this.getLabel(props.value), })); } } _onChange = (e) => { let newValue = ""; if (e.target.tagName === "LI" && e.target.textContent) newValue = e.target.textContent; else if (e.target.value) newValue = e.target.value; this.setState({ inputValue: newValue, }); }; _onFocus = (e) => { if (this.props.onInputFocus) this.props.onInputFocus(e); }; /** Autosuggest will call this function every time you need to update suggestions. */ _onSuggestionsFetchRequested = async (request) => { const value = request.value; const suggestions = await this._getSuggestions(value); if (this._isMounted) this.setState({ suggestions }); }; /** Autosuggest will call this function every time you need to clear suggestions. */ _onSuggestionsClearRequested = () => { this.setState({ suggestions: [] }); this.props.onSuggestionsClearRequested && this.props.onSuggestionsClearRequested(); }; _onSuggestionSelected = (_event, data) => { this.props.onSuggestionSelected(data.suggestion); }; /** Teach Autosuggest how to calculate suggestions for any given input value. */ _getSuggestions = async (value) => { if (typeof this.props.options === "function") return Promise.resolve(this.props.options(value)); if (this.props.getSuggestions) return this.props.getSuggestions(value); if (this.props.options === undefined) { Logger.logError(UiCore.loggerCategory("AutoSuggest"), `props.options or props.getSuggestions should be provided`); return Promise.resolve([]); } const inputValue = value.trim().toLowerCase(); const inputLength = inputValue.length; return Promise.resolve(inputLength === 0 ? [] : this.props.options.filter((data) => { return (data.label.toLowerCase().includes(inputValue) || data.value.toLowerCase().includes(inputValue)); })); }; /** When suggestion is clicked, Autosuggest needs to populate the input based on the clicked suggestion. */ _getSuggestionValue = (suggestion) => suggestion.label; /** Render each suggestion. */ _renderSuggestion = (suggestion) => (React.createElement("span", null, suggestion.label)); getLabel(value) { let label = ""; if (this.props.getLabel) { label = this.props.getLabel(value); } else if (this.props.options instanceof Array) { const entry = this.props.options.find((data) => data.value === value); if (entry) label = entry.label; } else { Logger.logError(UiCore.loggerCategory("AutoSuggest"), `props.getLabel should be provided when props.options is a function`); } return label; } _handleKeyDown = (e) => { switch (e.key) { case Key.Enter.valueOf(): if (this.props.onPressEnter) this.props.onPressEnter(e); break; case Key.Escape.valueOf(): if (this.props.onPressEscape) this.props.onPressEscape(e); break; case Key.Tab.valueOf(): if (this.props.onPressTab) this.props.onPressTab(e); break; } }; _theme = { container: "uicore-autosuggest__container", containerOpen: "uicore-autosuggest__container--open", input: "uicore-autosuggest__input", inputOpen: "uicore-autosuggest__input--open", inputFocused: "uicore-autosuggest__input--focused", suggestionsContainer: "uicore-autosuggest__suggestions-container", suggestionsContainerOpen: "uicore-autosuggest__suggestions-container--open", suggestionsList: "uicore-autosuggest__suggestions-list", suggestion: "uicore-autosuggest__suggestion", suggestionFirst: "uicore-autosuggest__suggestion--first", suggestionHighlighted: "uicore-autosuggest__suggestion--highlighted", sectionContainer: "uicore-autosuggest__section-container", sectionContainerFirst: "uicore-autosuggest__section-container--first", sectionTitle: "uicore-autosuggest__section-title", }; render() { const { inputValue, suggestions } = this.state; const { value, onChange, placeholder, options, onSuggestionSelected, setFocus, alwaysRenderSuggestions, onPressEnter, onPressEscape, onPressTab, onInputFocus, getLabel, getSuggestions, renderInputComponent, renderSuggestionsContainer, onSuggestionsClearRequested, ...props } = this.props; const inputPlaceholder = !inputValue ? placeholder : undefined; const inputProps = { ...props, value: inputValue, onChange: this._onChange, onFocus: this._onFocus, placeholder: inputPlaceholder, autoFocus: setFocus, }; const defaultRenderInputComponent = (renderInputProps) => { const { size, ...other } = renderInputProps; return React.createElement(Input, { ...other }); }; return ( // The onKeyDown event handler is only being used to capture bubbled events // eslint-disable-next-line jsx-a11y/no-static-element-interactions React.createElement("div", { className: this.props.className, style: this.props.style, onKeyDown: this._handleKeyDown }, React.createElement(ReactAutosuggest, { theme: this._theme, suggestions: suggestions, onSuggestionsFetchRequested: this._onSuggestionsFetchRequested, onSuggestionsClearRequested: this._onSuggestionsClearRequested, getSuggestionValue: this._getSuggestionValue, renderSuggestion: this._renderSuggestion, inputProps: inputProps, onSuggestionSelected: this._onSuggestionSelected, alwaysRenderSuggestions: alwaysRenderSuggestions, renderInputComponent: renderInputComponent || defaultRenderInputComponent, renderSuggestionsContainer: renderSuggestionsContainer }))); } } //# sourceMappingURL=AutoSuggest.js.map