import * as React from 'react'; import Autosuggest from 'react-autosuggest'; import { connectAutoComplete, Highlight, Snippet } from 'react-instantsearch-dom'; import { withRouter, RouteComponentProps } from 'react-router-dom'; 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 { searchIndices } from 'ts/utils/algolia_search'; interface IHit { description: string; difficulty: string; id: number | string; isCommunity?: boolean; isFeatured?: boolean; objectID: string; tags?: string[]; textContent: string; title: string; type?: string; url: string; _highlightResult: any; _snippetResult: any; } interface IAutoCompleteProps extends RouteComponentProps<{}> { isHome?: boolean; hits?: object[]; currentRefinement?: string; refine?: (value: string) => void; } interface ISnippetMatchLevels { [index: string]: number; } const SNIPPET_MATCH_LEVELS: ISnippetMatchLevels = { none: 0, partial: 1, full: 2 }; const CustomAutoComplete: React.FC = ({ isHome = false, hits = [], currentRefinement, refine, history, }) => { 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 onChange = (event: React.KeyboardEvent, { newValue, method }: any): void => { if (method === 'type') { setValue(newValue); } }; const onSuggestionsFetchRequested = ({ value: newValue }: any): void => refine(newValue); const onSuggestionsClearRequested = (): void => refine(''); const onSuggestionSelected = (event: React.KeyboardEvent, { suggestion }: any): void => { if (event.key === 'Enter' && suggestion.url) { // Without using route props / withRouter HOC this could simply be (with full page load): // location.href = suggestion.url; history.push(suggestion.url); window.scrollTo(0, 0); } setValue(''); // Clear input value inputRef.blur(); // Blur input, used for keyboard choices in connection with focusInputOnSuggestionClick prop on autosuggest for mouse clicks }; const getSuggestionValue = (hit: IHit): string => hit.textContent; const renderSuggestion = (hit: IHit): React.ReactNode => { const description: string = hit._snippetResult.description.matchLevel; const textContent: string = hit._snippetResult.textContent.matchLevel; let attributeToSnippet = 'description'; if (SNIPPET_MATCH_LEVELS[textContent] > SNIPPET_MATCH_LEVELS[description]) { attributeToSnippet = 'textContent'; } return ( ); }; const renderSectionTitle = (section: any): React.ReactNode => { const { tools, guides } = searchIndices; const coreConcepts = searchIndices['core-concepts']; const titles: { [key: string]: string } = { [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 inputProps = { placeholder: 'Search docs…', onChange, value, }; return ( <> {currentRefinement && ( )} ); }; export const AutoComplete = connectAutoComplete(withRouter(CustomAutoComplete));