Created
March 11, 2022 22:35
-
-
Save justinbhopper/920d8450da875a380c8c0fd5286cfe29 to your computer and use it in GitHub Desktop.
Suggest enhancement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { Button } from "@blueprintjs/core"; | |
import * as Core from "@blueprintjs/select"; | |
export interface SuggestProps<T> extends Omit<Core.SuggestProps<T>, "onItemSelect"> { | |
/** | |
* If true, defaults the `inputProps.rightElement` to a clear button that will clear the selection. | |
* Ignored if `inputProps.rightElement` is provided. | |
* @default false | |
*/ | |
clearable?: boolean; | |
/** | |
* Invoked when the selection changes or is cleared. | |
*/ | |
onItemSelect?: (item: T | null, event?: React.SyntheticEvent<HTMLElement>) => void; | |
} | |
interface SuggestState<T> { | |
selectedItem: T | null; | |
query: string; | |
} | |
export class Suggest<T> extends React.PureComponent<SuggestProps<T>, SuggestState<T>> { | |
private readonly TypedSuggest = Core.Suggest.ofType<T>(); | |
constructor(props: SuggestProps<T>) { | |
super(props); | |
this.state = { | |
query: "", | |
selectedItem: props.defaultSelectedItem ?? null, | |
}; | |
} | |
public static ofType<T>() { | |
return Suggest as new (props: SuggestProps<T>) => Suggest<T>; | |
} | |
public componentDidUpdate(prevProps: SuggestProps<T>) { | |
const { selectedItem } = this.props; | |
// Announce new value if prop changed | |
if (selectedItem && selectedItem !== prevProps.selectedItem) { | |
this.setState({ selectedItem }); | |
} | |
} | |
public render() { | |
const { | |
clearable = false, | |
onItemSelect, | |
query = this.state.query, | |
selectedItem = this.state.selectedItem, | |
inputProps = {}, | |
...restProps | |
} = this.props; | |
const { rightElement: controlledRightElement, ...restInputProps } = inputProps; | |
let rightElement = controlledRightElement; | |
if (!rightElement && clearable && query) { | |
rightElement = ( | |
<Button minimal icon="cross" onClick={this.handleClear} /> | |
); | |
} | |
return ( | |
<this.TypedSuggest | |
{...restProps} | |
inputProps={{ | |
...restInputProps, | |
rightElement, | |
}} | |
query={query} | |
selectedItem={selectedItem} | |
onItemSelect={this.handleItemSelect} | |
onQueryChange={this.handleQueryChange} | |
/> | |
); | |
} | |
private handleItemSelect = (item: T, event?: React.SyntheticEvent<HTMLElement>) => { | |
this.props.onItemSelect?.(item, event); | |
this.handleSelectedItemChange(item); | |
}; | |
private handleClear = (): void => { | |
this.handleSelectedItemChange(null); | |
// Clear query on clear button too | |
this.handleQueryChange(""); | |
}; | |
private handleSelectedItemChange = (selectedItem: T | null): void => { | |
const { onItemSelect } = this.props; | |
onItemSelect?.(selectedItem); | |
this.setState({ selectedItem }); | |
}; | |
private handleQueryChange = (query: string, event?: React.ChangeEvent<HTMLInputElement>): void => { | |
this.props.onQueryChange?.(query, event); | |
this.setState({ query }); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment