UNPKG

@atlaskit/global-search

Version:

A cross-product search component (batteries included)

209 lines (182 loc) 6.52 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import debounce from 'lodash/debounce'; import { QuickSearch } from '@atlaskit/quick-search'; import { withAnalyticsEvents, AnalyticsContext } from '@atlaskit/analytics-next'; import { fireSelectedSearchResult, fireHighlightedSearchResult, fireSelectedAdvancedSearch, fireTextEnteredEvent, fireDismissedEvent, fireAutocompleteRenderedEvent, fireAutocompleteCompletedEvent } from '../util/analytics-event-helper'; import { isAdvancedSearchResult } from './SearchResultsUtil'; import { getAutocompleteText } from '../util/autocomplete'; const ATLASKIT_QUICKSEARCH_NS = 'atlaskit.navigation.quick-search'; const QS_ANALYTICS_EV_KB_CTRLS_USED = `${ATLASKIT_QUICKSEARCH_NS}.keyboard-controls-used`; const QS_ANALYTICS_EV_SUBMIT = `${ATLASKIT_QUICKSEARCH_NS}.submit`; /** * Presentational component that renders the search input and search results. */ export class GlobalQuickSearch extends React.Component { constructor(...args) { super(...args); _defineProperty(this, "queryVersion", 0); _defineProperty(this, "autoCompleteVersion", 0); _defineProperty(this, "autoCompleteLastTimeStamp", 0); _defineProperty(this, "resultSelected", false); _defineProperty(this, "state", { query: '', autocompleteText: undefined }); _defineProperty(this, "handleSearchInput", ({ target }, isAutocompleted) => { const query = target.value; this.debouncedSearch(query); if (query.length > 0) { this.autoCompleteLastTimeStamp = +new Date(); this.debouncedAutocomplete(query); } if (isAutocompleted) { const { searchSessionId, createAnalyticsEvent } = this.props; const { query: prevQuery } = this.state; fireAutocompleteCompletedEvent(searchSessionId, prevQuery, query, createAnalyticsEvent); } this.setState({ query }); }); _defineProperty(this, "debouncedSearch", debounce(this.doSearch, 350)); _defineProperty(this, "debouncedAutocomplete", debounce(this.doAutocomplete, 100)); _defineProperty(this, "fireSearchResultSelectedEvent", eventData => { const { createAnalyticsEvent, searchSessionId, referralContextIdentifiers, advancedSearchId } = this.props; this.resultSelected = true; const resultId = eventData.resultCount && eventData.method === 'shortcut' ? advancedSearchId : eventData.resultId; if (isAdvancedSearchResult(resultId)) { fireSelectedAdvancedSearch({ ...eventData, resultId, query: this.state.query, queryVersion: this.queryVersion, isLoading: this.props.isLoading }, searchSessionId, referralContextIdentifiers, createAnalyticsEvent); } else { fireSelectedSearchResult({ ...eventData, query: this.state.query, queryVersion: this.queryVersion }, searchSessionId, referralContextIdentifiers, createAnalyticsEvent); } }); _defineProperty(this, "fireSearchResultEvents", (eventName, eventData) => { const { createAnalyticsEvent, searchSessionId, referralContextIdentifiers } = this.props; if (eventName === QS_ANALYTICS_EV_SUBMIT) { this.fireSearchResultSelectedEvent(eventData); } else if (eventName === QS_ANALYTICS_EV_KB_CTRLS_USED) { const data = eventData; if (data.key === 'ArrowDown' || data.key === 'ArrowUp') { fireHighlightedSearchResult(data, searchSessionId, referralContextIdentifiers, createAnalyticsEvent); } } }); } static getDerivedStateFromProps(nextProps, prevState) { const { autocompleteSuggestions } = nextProps; const { query } = prevState; return { ...prevState, autocompleteText: getAutocompleteText(query, autocompleteSuggestions) }; } componentDidMount() { this.props.onMount && this.props.onMount(); } componentDidUpdate(prevProps, prevState) { const { createAnalyticsEvent, searchSessionId, autocompleteSuggestions } = this.props; const { query, autocompleteText } = this.state; if (query.length > 0 && autocompleteText && autocompleteText.length > query.length && (query !== prevState.query || autocompleteText !== prevState.autocompleteText)) { const duration = +new Date() - this.autoCompleteLastTimeStamp; fireAutocompleteRenderedEvent(duration, searchSessionId, query, autocompleteText, this.autoCompleteVersion, autocompleteSuggestions === prevProps.autocompleteSuggestions, createAnalyticsEvent); this.autoCompleteLastTimeStamp = +new Date(); this.autoCompleteVersion++; } } doSearch(query) { const { onSearch, searchSessionId, createAnalyticsEvent, filters } = this.props; onSearch(query.trim(), this.queryVersion, filters); fireTextEnteredEvent(query, searchSessionId, this.queryVersion, createAnalyticsEvent); this.queryVersion++; } doAutocomplete(query) { const { onAutocomplete } = this.props; onAutocomplete && onAutocomplete(query); } componentWillUnmount() { if (this.resultSelected) { return; } const { createAnalyticsEvent, searchSessionId } = this.props; fireDismissedEvent(searchSessionId, createAnalyticsEvent); } render() { const { isLoading, placeholder, linkComponent, children, onSearchSubmit, selectedResultId, onSelectedResultIdChanged, inputControls } = this.props; const { query, autocompleteText } = this.state; return /*#__PURE__*/React.createElement(AnalyticsContext, { data: { searchSessionId: this.props.searchSessionId } }, /*#__PURE__*/React.createElement(QuickSearch, { firePrivateAnalyticsEvent: this.fireSearchResultEvents, isLoading: isLoading, onSearchInput: this.handleSearchInput, placeholder: placeholder, value: query, linkComponent: linkComponent, onSearchSubmit: onSearchSubmit, selectedResultId: selectedResultId, onSelectedResultIdChanged: onSelectedResultIdChanged, inputControls: inputControls, autocompleteText: autocompleteText }, children)); } } export default withAnalyticsEvents()(GlobalQuickSearch);