From b67f8f2a4f6c0b3ec9be77c0381100e1aa24bf65 Mon Sep 17 00:00:00 2001 From: Oliver Joseph Ash Date: Tue, 22 Oct 2019 21:48:38 +0100 Subject: [PATCH] react-autosuggest: add support for sections (#39212) * react-autosuggest: add support for sections * Update deps * Remove test as suggested Re. https://github.com/DefinitelyTyped/DefinitelyTyped/pull/39212#discussion_r337053458 * Revert "Update deps" This reverts commit 0bb7fcf74e8d8511c061261e15a4f5c49d241abb. --- types/react-autosuggest/index.d.ts | 58 +++++++++------ .../react-autosuggest-tests.tsx | 42 ++++++++++- .../react-instantsearch-core-tests.tsx | 70 ------------------- 3 files changed, 76 insertions(+), 94 deletions(-) diff --git a/types/react-autosuggest/index.d.ts b/types/react-autosuggest/index.d.ts index ae6d89829e..7bcd3c96a6 100644 --- a/types/react-autosuggest/index.d.ts +++ b/types/react-autosuggest/index.d.ts @@ -9,12 +9,12 @@ // Thomas den Hollander // ulrichb // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.2 import * as React from 'react'; -declare class Autosuggest extends React.Component< - Autosuggest.AutosuggestProps, +declare class Autosuggest extends React.Component< + Autosuggest.AutosuggestProps, Autosuggest.AutosuggestState > { /** @@ -111,7 +111,7 @@ declare namespace Autosuggest { } // types for functions - allowing reuse externally - e.g. as props and bound in the constructor - type GetSectionSuggestions = (section: any) => TSuggestion[]; + type GetSectionSuggestions = (section: TSection) => TSuggestion[]; type GetSuggestionValue = (suggestion: TSuggestion) => string; type OnSuggestionHighlighted = (params: SuggestionHighlightedParams) => void; type SuggestionsFetchRequested = (request: SuggestionsFetchRequestedParams) => void; @@ -129,7 +129,7 @@ declare namespace Autosuggest { ) => React.ReactNode; type ShouldRenderSuggestions = (value: string) => boolean; - interface AutosuggestProps { + interface AutosuggestPropsBase { /** * Set it to true if you'd like to render suggestions even when the input is not focused. */ @@ -138,10 +138,6 @@ declare namespace Autosuggest { * Set it to false if you don't want Autosuggest to keep the input focused when suggestions are clicked/tapped. */ focusInputOnSuggestionClick?: boolean; - /** - * Implement it to teach Autosuggest where to find the suggestions for every section. - */ - getSectionSuggestions?: GetSectionSuggestions; /** * Implement it to teach Autosuggest what should be the input value when suggestion is clicked. */ @@ -158,10 +154,6 @@ declare namespace Autosuggest { * Pass through arbitrary props to the input. It must contain at least value and onChange. */ inputProps: InputProps; - /** - * Set it to true if you'd like to display suggestions in multiple sections (with optional titles). - */ - multiSection?: boolean; /** * Will be called every time the highlighted suggestion changes. */ @@ -186,10 +178,6 @@ declare namespace Autosuggest { * Use it if you want to customize things inside the suggestions container beyond rendering the suggestions themselves. */ renderSuggestionsContainer?: RenderSuggestionsContainer; - /** - * Use your imagination to define how section titles are rendered. - */ - renderSectionTitle?: RenderSectionTitle; /** * Use your imagination to define how suggestions are rendered. */ @@ -199,16 +187,44 @@ declare namespace Autosuggest { * Use it, for example, if you want to display suggestions when input value is at least 2 characters long. */ shouldRenderSuggestions?: ShouldRenderSuggestions; - /** - * These are the suggestions that will be displayed. Items can take an arbitrary shape. - */ - suggestions: ReadonlyArray; /** * Use your imagination to style the Autosuggest. */ theme?: Theme; } + interface AutosuggestPropsSingleSection extends AutosuggestPropsBase { + /** + * Set it to true if you'd like to display suggestions in multiple sections (with optional titles). + */ + multiSection?: false; + /** + * These are the suggestions that will be displayed. Items can take an arbitrary shape. + */ + suggestions: ReadonlyArray; + } + + interface AutosuggestPropsMultiSection extends AutosuggestPropsBase { + /** + * Set it to true if you'd like to display suggestions in multiple sections (with optional titles). + */ + multiSection: true; + /** + * These are the suggestions that will be displayed. Items can take an arbitrary shape. + */ + suggestions: ReadonlyArray; + /** + * Implement it to teach Autosuggest where to find the suggestions for every section. + */ + getSectionSuggestions?: GetSectionSuggestions; + /** + * Use your imagination to define how section titles are rendered. + */ + renderSectionTitle?: RenderSectionTitle; + } + + type AutosuggestProps = AutosuggestPropsSingleSection | AutosuggestPropsMultiSection; + interface AutosuggestState { isFocused: boolean; isCollapsed: boolean; diff --git a/types/react-autosuggest/react-autosuggest-tests.tsx b/types/react-autosuggest/react-autosuggest-tests.tsx index 2a1eb42c4c..d69dc5cc8d 100644 --- a/types/react-autosuggest/react-autosuggest-tests.tsx +++ b/types/react-autosuggest/react-autosuggest-tests.tsx @@ -133,7 +133,8 @@ export class ReactAutosuggestBasicTest extends React.Component { // endregion } -const LanguageAutosuggest = Autosuggest as { new (): Autosuggest }; +const LanguageAutosuggestSingle = Autosuggest as { new (): Autosuggest }; +const LanguageAutosuggestMulti = Autosuggest as { new (): Autosuggest }; export class ReactAutosuggestTypedTest extends React.Component { // region Fields @@ -198,7 +199,7 @@ export class ReactAutosuggestTypedTest extends React.Component { sectionTitle: { color: 'blue' } }; - return { render(): JSX.Element { const {value, suggestions} = this.state; - return = { value: 'foo', anything: false // $ExpectError }; + +function testSingleSection() { + const suggestions: string[] = []; + suggestion} + inputProps={{ + onChange: () => {}, + value: '' + }} + onSuggestionsFetchRequested={() => {}} + renderSuggestion={suggestion => suggestion} + />; +} + +function testMultiSections() { + interface Section { title: string; suggestions: string[]; } + const sections: Section[] = []; + section.suggestions} + + // Required + getSuggestionValue={(suggestion: string) => suggestion} + inputProps={{ + onChange: () => {}, + value: '' + }} + onSuggestionsFetchRequested={() => {}} + renderSuggestion={suggestion => suggestion} + />; +} diff --git a/types/react-instantsearch-core/react-instantsearch-core-tests.tsx b/types/react-instantsearch-core/react-instantsearch-core-tests.tsx index 3d0208707e..d457848c5f 100644 --- a/types/react-instantsearch-core/react-instantsearch-core-tests.tsx +++ b/types/react-instantsearch-core/react-instantsearch-core-tests.tsx @@ -438,76 +438,6 @@ import { ; }; -// https://github.com/algolia/react-instantsearch/blob/master/examples/autocomplete/src/App-Multi-Index.js -import * as Autosuggest from 'react-autosuggest'; -() => { - class Example extends React.Component { - state = { - value: this.props.currentRefinement, - }; - - onChange = (_event: any, { newValue }: { newValue: string }) => { - this.setState({ - value: newValue, - }); - } - - onSuggestionsFetchRequested = ({ value }: { value: string }) => { - this.props.refine(value); - } - - onSuggestionsClearRequested = () => { - this.props.refine(); - } - - getSuggestionValue(hit: Hit) { - return hit.name; - } - - renderSuggestion(hit: Hit) { - const Highlight: any = null; // import {Highlight} from 'react-instantsearch-dom' - return ; - } - - renderSectionTitle(section: any) { - return section.index; - } - - getSectionSuggestions(section: any) { - return section.hits; - } - - render() { - const { hits } = this.props; - const { value } = this.state; - - const inputProps = { - placeholder: 'Search for a product...', - onChange: this.onChange, - value, - }; - - return ( - - ); - } - } - - const AutoComplete = connectAutoComplete(Example); - - ; -}; - () => { type Props = SearchBoxProvided & TranslatableProvided & { className?: string