import {createRef, PureComponent} from 'react'; import styled from '@emotion/styled'; import classNames from 'classnames'; import Button from 'sentry/components/button'; import Input, {InputProps} from 'sentry/components/forms/controls/input'; import {IconSearch} from 'sentry/icons'; import {IconClose} from 'sentry/icons/iconClose'; import {t} from 'sentry/locale'; import {callIfFunction} from 'sentry/utils/callIfFunction'; interface SearchBarProps extends Omit { defaultQuery: string; onSearch: (query: string) => void; query: string; onChange?: (query: string) => void; width?: string; } type State = { dropdownVisible: boolean; query: string; }; class SearchBar extends PureComponent { static defaultProps: Pick = { query: '', defaultQuery: '', onSearch: function () {}, }; state: State = { query: this.props.query || this.props.defaultQuery, dropdownVisible: false, }; UNSAFE_componentWillReceiveProps(nextProps: SearchBarProps) { if (nextProps.query !== this.props.query) { this.setState({ query: nextProps.query, }); } } searchInputRef = createRef(); blur = () => { if (this.searchInputRef.current) { this.searchInputRef.current.blur(); } }; onSubmit = (evt: React.FormEvent) => { evt.preventDefault(); this.blur(); this.props.onSearch(this.state.query); }; clearSearch = () => { this.setState({query: this.props.defaultQuery}, () => { this.props.onSearch(this.state.query); callIfFunction(this.props.onChange, this.state.query); }); }; onQueryFocus = () => { this.setState({ dropdownVisible: true, }); }; onQueryBlur = () => { this.setState({dropdownVisible: false}); }; onQueryChange = (evt: React.ChangeEvent) => { const {value} = evt.target; this.setState({query: value}); callIfFunction(this.props.onChange, value); }; render() { // Remove keys that should not be passed into Input const { className, width, query: _q, defaultQuery, onChange: _oC, onSearch: _oS, ...inputProps } = this.props; return (
{this.state.query !== defaultQuery && ( } aria-label={t('Clear')} /> )}
); } } const StyledInput = styled(Input)` width: ${p => (p.width ? p.width : undefined)}; &.focus-visible { box-shadow: 0 0 0 1px ${p => p.theme.focusBorder}; border-color: ${p => p.theme.focusBorder}; outline: none; } `; const StyledIconSearch = styled(IconSearch)` position: absolute; top: 50%; transform: translateY(-50%); left: 14px; `; const SearchClearButton = styled(Button)` position: absolute; top: 50%; height: 16px; transform: translateY(-50%); right: 10px; font-size: ${p => p.theme.fontSizeLarge}; color: ${p => p.theme.gray200}; &:hover { color: ${p => p.theme.gray300}; } `; export default SearchBar;