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.
This commit is contained in:
Oliver Joseph Ash 2019-10-22 21:48:38 +01:00 committed by Wesley Wigham
parent 219d7a809b
commit b67f8f2a4f
3 changed files with 76 additions and 94 deletions

View File

@ -9,12 +9,12 @@
// Thomas den Hollander <https://github.com/ThomasdenH>
// ulrichb <https://github.com/ulrichb>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.8
// TypeScript Version: 3.2
import * as React from 'react';
declare class Autosuggest<T = any> extends React.Component<
Autosuggest.AutosuggestProps<T>,
declare class Autosuggest<T = any, T2 = any> extends React.Component<
Autosuggest.AutosuggestProps<T, T2>,
Autosuggest.AutosuggestState<T>
> {
/**
@ -111,7 +111,7 @@ declare namespace Autosuggest {
}
// types for functions - allowing reuse externally - e.g. as props and bound in the constructor
type GetSectionSuggestions<TSuggestion> = (section: any) => TSuggestion[];
type GetSectionSuggestions<TSuggestion, TSection> = (section: TSection) => TSuggestion[];
type GetSuggestionValue<TSuggestion> = (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<TSuggestion> {
interface AutosuggestPropsBase<TSuggestion> {
/**
* 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<TSuggestion>;
/**
* 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<TSuggestion>;
/**
* 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<TSuggestion>;
/**
* Use your imagination to style the Autosuggest.
*/
theme?: Theme;
}
interface AutosuggestPropsSingleSection<TSuggestion> extends AutosuggestPropsBase<TSuggestion> {
/**
* 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<TSuggestion>;
}
interface AutosuggestPropsMultiSection<TSuggestion, TSection> extends AutosuggestPropsBase<TSuggestion> {
/**
* 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<TSection>;
/**
* Implement it to teach Autosuggest where to find the suggestions for every section.
*/
getSectionSuggestions?: GetSectionSuggestions<TSuggestion, TSection>;
/**
* Use your imagination to define how section titles are rendered.
*/
renderSectionTitle?: RenderSectionTitle;
}
type AutosuggestProps<TSuggestion, TSection> = AutosuggestPropsSingleSection<TSuggestion> | AutosuggestPropsMultiSection<TSuggestion, TSection>;
interface AutosuggestState<TSuggestion> {
isFocused: boolean;
isCollapsed: boolean;

View File

@ -133,7 +133,8 @@ export class ReactAutosuggestBasicTest extends React.Component<any, any> {
// endregion
}
const LanguageAutosuggest = Autosuggest as { new (): Autosuggest<Language> };
const LanguageAutosuggestSingle = Autosuggest as { new (): Autosuggest<Language> };
const LanguageAutosuggestMulti = Autosuggest as { new (): Autosuggest<Language, LanguageGroup> };
export class ReactAutosuggestTypedTest extends React.Component<any, any> {
// region Fields
@ -198,7 +199,7 @@ export class ReactAutosuggestTypedTest extends React.Component<any, any> {
sectionTitle: { color: 'blue' }
};
return <LanguageAutosuggest
return <LanguageAutosuggestSingle
suggestions={suggestions}
onSuggestionsFetchRequested={this
.onSuggestionsFetchRequested
@ -348,7 +349,7 @@ export class ReactAutosuggestMultipleTest extends React.Component<any, any> {
render(): JSX.Element {
const {value, suggestions} = this.state;
return <LanguageAutosuggest
return <LanguageAutosuggestMulti
multiSection={true}
suggestions={suggestions}
onSuggestionsFetchRequested={this
@ -564,3 +565,38 @@ const test: Autosuggest.InputProps<{ foo: string }> = {
value: 'foo',
anything: false // $ExpectError
};
function testSingleSection() {
const suggestions: string[] = [];
<Autosuggest
suggestions={suggestions}
// Required
getSuggestionValue={suggestion => suggestion}
inputProps={{
onChange: () => {},
value: ''
}}
onSuggestionsFetchRequested={() => {}}
renderSuggestion={suggestion => suggestion}
/>;
}
function testMultiSections() {
interface Section { title: string; suggestions: string[]; }
const sections: Section[] = [];
<Autosuggest
multiSection
suggestions={sections}
getSectionSuggestions={section => section.suggestions}
// Required
getSuggestionValue={(suggestion: string) => suggestion}
inputProps={{
onChange: () => {},
value: ''
}}
onSuggestionsFetchRequested={() => {}}
renderSuggestion={suggestion => suggestion}
/>;
}

View File

@ -438,76 +438,6 @@ import {
<ConnectedAsyncMention />;
};
// 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<AutocompleteProvided> {
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 <Highlight attribute="name" hit={hit} tagName="mark" />;
}
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 (
<Autosuggest
suggestions={hits}
multiSection={true}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
getSuggestionValue={this.getSuggestionValue}
renderSuggestion={this.renderSuggestion}
inputProps={inputProps}
renderSectionTitle={this.renderSectionTitle}
getSectionSuggestions={this.getSectionSuggestions}
/>
);
}
}
const AutoComplete = connectAutoComplete(Example);
<AutoComplete />;
};
() => {
type Props = SearchBoxProvided & TranslatableProvided & {
className?: string