import * as React from 'react'; import Autosuggest from 'react-autosuggest'; import { connectAutoComplete, Highlight, Snippet } from 'react-instantsearch-dom'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { scroller } from 'react-scroll'; import { Link } from 'ts/components/documentation/shared/link'; import { AutocompleteOverlay } from 'ts/components/docs/search/autocomplete_overlay'; import { AutocompleteWrapper } from 'ts/components/docs/search/autocomplete_wrapper'; import { docs } from 'ts/style/docs'; import { searchIndices } from 'ts/utils/algolia_constants'; interface IHit { description: string; difficulty?: string; externalUrl?: string; hash?: string; id: number | string; isCommunity?: boolean; isFeatured?: boolean; objectID: string; sectionUrl: string; tags?: string[]; textContent: string; title: string; type?: string; url?: string; urlWithHash?: string; _highlightResult?: any; _snippetResult?: any; } interface IAutoCompleteProps extends RouteComponentProps<{}> { isHome?: boolean; hits?: object[]; currentRefinement?: string; refine?: (value: string) => void; } const CustomAutoComplete: React.FC = ({ isHome = false, hits = [], currentRefinement, refine, history, location, }) => { const [value, setValue] = React.useState(''); let inputRef: HTMLInputElement; React.useEffect(() => { const handleKeyUp: any = (event: React.KeyboardEvent): void => { if (event.key === 'Escape') { setValue(''); inputRef.blur(); } }; window.addEventListener('keyup', handleKeyUp); return () => { window.removeEventListener('keyup', handleKeyUp); }; }, []); const onSuggestionsFetchRequested = ({ value: newValue }: { value: string }): void => refine(newValue); const onSuggestionsClearRequested = (): void => refine(''); const onSuggestionSelected = (event: React.KeyboardEvent, { suggestion }: any): void => { const { externalUrl, hash, url, urlWithHash } = suggestion; if (!externalUrl) { // If there is a hash (fragment identifier) and the user is currently // on the same page, scroll to content. If not, route away to the doc page. if (hash && location.pathname === url) { const id = hash.substring(1); // Get rid of # symbol scroller.scrollTo(id, { smooth: true, duration: docs.scrollDuration, offset: -docs.headerOffset, }); } else { history.push(urlWithHash); window.scrollTo(0, 0); } } setValue(''); // Clear input value inputRef.blur(); // Blur input }; const getSuggestionValue = (hit: IHit): string => hit.textContent; const renderSuggestion = (hit: IHit): React.ReactNode => { const { externalUrl, urlWithHash } = hit; const to = externalUrl ? externalUrl : urlWithHash; return ( ); }; const renderSectionTitle = (section: any): React.ReactNode => { const { tools, guides } = searchIndices; const coreConcepts = searchIndices['core-concepts']; // TODO: Add this back in when api - explorer page is ready // to be indexed and included in the search results (ditto in search_input.tsx) // const apiExplorer = searchIndices['api-explorer']; const titles: { [key: string]: string } = { // TODO: Add this back in when api - explorer page is ready // to be indexed and included in the search results (ditto in search_input.tsx) // [apiExplorer]: 'Api explorer', [coreConcepts]: 'Core concepts', [tools]: 'Tools', [guides]: 'Guides', }; if (section.hits.length) { return

{titles[section.index]}

; } return null; }; const getSectionSuggestions = (section: any): string => section.hits; const storeInputRef = (autosuggest: any): void => { if (autosuggest !== null) { inputRef = autosuggest.input; } }; const onChange = (event: React.KeyboardEvent, { newValue, method }: { newValue: string; method: string }): void => { // Only set value if the user typed it in, without it it leads to populating the input with snippet or highlight text if (method === 'type') { setValue(newValue); } }; const inputProps = { placeholder: 'Search docs…', onChange, value, }; return ( <> {currentRefinement && ( )} ); }; export const AutoComplete = connectAutoComplete(withRouter(CustomAutoComplete));