UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

88 lines (87 loc) 3.76 kB
import "../../CommonImports"; import "../../Core/core.css"; import * as React from "react"; import { TextField } from "../TextField/TextField"; import { ObservableLike } from '../../Core/Observable'; import { css, KeyCode } from '../../Util'; export class TypeAhead extends React.Component { constructor() { super(...arguments); this.textFieldRef = React.createRef(); this.autofillEnabled = true; this.select = () => { this.textFieldRef.current.select(); }; this.onKeyDown = (event) => { this.props.onKeyDown && this.props.onKeyDown(event); if (event.isDefaultPrevented()) { return; } const suggestedValue = this.props.suggestedValue && ObservableLike.getValue(this.props.suggestedValue); const typedValue = this.props.value && ObservableLike.getValue(this.props.value); switch (event.which) { case KeyCode.tab: if (suggestedValue && typedValue !== suggestedValue && this.autofillEnabled && this.props.onAutoComplete) { this.props.onAutoComplete(suggestedValue); event.preventDefault(); } break; case KeyCode.backspace: case KeyCode.delete: this.autofillEnabled = false; break; default: this.autofillEnabled = true; break; } }; } // We have to use this paradigm because otherwise componentDidUpdate won't get called subscribeAll(props) { ObservableLike.subscribe(props.value, () => this.forceUpdate()); ObservableLike.subscribe(props.suggestedValue, () => this.forceUpdate()); } unsubscribeAll(props) { ObservableLike.unsubscribe(props.value, () => this.forceUpdate()); ObservableLike.unsubscribe(props.suggestedValue, () => this.forceUpdate()); } componentDidMount() { this.subscribeAll(this.props); } componentWillUnmount() { this.unsubscribeAll(this.props); } UNSAFE_componentWillReceiveProps(newProps) { this.unsubscribeAll(this.props); this.subscribeAll(newProps); } focus() { this.textFieldRef.current.focus(); } get selectionEnd() { return this.textFieldRef.current.selectionEnd; } get selectionStart() { return this.textFieldRef.current.selectionStart; } setSelectionRange(start, end, direction) { this.textFieldRef.current.setSelectionRange(start, end, direction); } render() { const { value, suggestedValue, className } = this.props; const renderValue = this.autofillEnabled ? suggestedValue : value; return (React.createElement(TextField, Object.assign({}, this.props, { className: css(className, "bolt-typeahead"), onKeyDown: this.onKeyDown, ref: this.textFieldRef, value: renderValue }))); } componentDidUpdate() { const suggestedValue = this.props.suggestedValue && ObservableLike.getValue(this.props.suggestedValue); const typedValue = this.props.value && ObservableLike.getValue(this.props.value); if (suggestedValue && this.autofillEnabled) { if (typedValue && suggestedValue.startsWith(typedValue)) { this.textFieldRef.current.setSelectionRange(typedValue.length, suggestedValue.length, "backward"); } else if (!typedValue) { this.textFieldRef.current.setSelectionRange(0, suggestedValue.length); } } } }