diff --git a/CHANGELOG.md b/CHANGELOG.md index 68196a7..dc2a09a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +## [7.6.0] 2022-08-22 + +### Changes + +- Additional props passed down to `AutocompleteInput` now get forwarded to the underlying input field + ## [7.5.0] 2022-08-19 ### Added diff --git a/package.json b/package.json index f2ad97a..1b36d99 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@perimetre/ui", "description": "A component library made by @perimetre", - "version": "7.5.0", + "version": "7.6.0", "repository": { "type": "git", "url": "git+https://github.com/perimetre/ui.git" diff --git a/src/components/AutocompleteInput/AutocompleteInput.stories.tsx b/src/components/AutocompleteInput/AutocompleteInput.stories.tsx index 6d4a8a3..146cded 100644 --- a/src/components/AutocompleteInput/AutocompleteInput.stories.tsx +++ b/src/components/AutocompleteInput/AutocompleteInput.stories.tsx @@ -71,8 +71,13 @@ const ControlledTemplate: Story (item ? item.label : '')} filterItem={(item, inputValue) => item.label.toLowerCase().includes(inputValue.toLowerCase())} - selectedItem={state} + selectedItem={state || null} onItemToggle={(item) => setState(item || undefined)} + onChange={(e) => { + if (e.target.value === '') { + setState(undefined); + } + }} /> ); }; diff --git a/src/components/AutocompleteInput/index.tsx b/src/components/AutocompleteInput/index.tsx index 2ad1810..84610b9 100644 --- a/src/components/AutocompleteInput/index.tsx +++ b/src/components/AutocompleteInput/index.tsx @@ -1,3 +1,5 @@ +// We turn off unused variables because in here. "props" are passed down to the input. But the react element doesn't expect the same props as downshift. So we have to destructure them but not use it +/* eslint-disable @typescript-eslint/no-unused-vars */ import classnames from 'classnames'; import Downshift, { ControllerStateAndHelpers } from 'downshift'; import { debounce } from 'lodash'; @@ -78,6 +80,10 @@ export type AutocompleteInputProps = * The render function used to render the dropdown item */ renderItem?: (item: Item, isSelected: boolean, isHighlighted: boolean) => React.ReactNode; + /** + * The render function used to render the blank slate + */ + renderBlankState?: (selectItem: (item: Item) => void) => React.ReactNode; /** * The component classname */ @@ -103,10 +109,10 @@ type DownshiftAutocompleteContentProps = ControllerStateAndHelpers & * * @param props the react component props * @param props.options The options that should be displayed in the dropdown -// * @param props.initialSelectedItem The initial selected item -// * @param props.displayRegardlessIfSearching Whether or not should always show the result list regardless if the user is searching or not. -// * @param props.onItemToggle A callback that is called every time the user selects or unselects an item -// * @param props.defaultValue The input defaultValue property + * @param props.initialSelectedItem The initial selected item + * @param props.displayRegardlessIfSearching Whether or not should always show the result list regardless if the user is searching or not. + * @param props.onItemToggle A callback that is called every time the user selects or unselects an item + * @param props.defaultValue The input defaultValue property * @param props.ignoreFilter Whether or not the options should be filtered based on user's input * @param props.filterItem Predicate to modify the items on display, for example, filter based on the value * @param props.itemToString Method used to convert the object item into the string that is shown on the dropdown @@ -114,6 +120,7 @@ type DownshiftAutocompleteContentProps = ControllerStateAndHelpers & * @param props.translations A translation object to override existing translations * @param props.renderButtons The render function used to render the option buttons * @param props.renderItem The render function used to render the dropdown item + * @param props.renderBlankState The render function used to render the blank slate * @param props.className The component classname * @param props.fetchMore A callback for when the input changes so more items can be loaded * @param props.shouldFetchOnInit Whether or not the options should be fetched on init @@ -126,15 +133,32 @@ type DownshiftAutocompleteContentProps = ControllerStateAndHelpers & * @param props.inputValue Downshift inputValue * @param props.highlightedIndex Downshift highlightedIndex * @param props.toggleMenu Downshift toggleMenu + * @param props.initialSelectedItem The item to already start selected if any + * @param props.clearItems Clear the list of items + * @param props.clearSelection Clear the currently selected item + * @param props.openMenu Open the dropdown + * @param props.closeMenu Close the dropdown + * @param props.getRootProps Method used to get props for the autocomplete wrapper + * @param props.getToggleButtonProps Method used to get props for the toggle button + * @param props.id The input id if any + * @param props.reset Reset the entire state + * @param props.selectHighlightedItem Select the currently highlighted item + * @param props.selectItem Select an item + * @param props.selectItemAtIndex Select the item from the index + * @param props.selectedItem The currently selected item + * @param props.setHighlightedIndex Set the index of what should be highlighted + * @param props.setItemCount Set the number of items the array currently has + * @param props.setState Set the entire downshift state + * @param props.unsetItemCount Reset the number of items the array currently has */ const DownshiftAutocompleteContent = ({ // Autocomplete props options, - // initialSelectedItem, - // displayRegardlessIfSearching, + initialSelectedItem, + displayRegardlessIfSearching, // displayRegardlessIfFocused, - // onItemToggle, - // defaultValue, + onItemToggle, + defaultValue, ignoreFilter, filterItem, itemToString, @@ -146,6 +170,7 @@ const DownshiftAutocompleteContent = ({ fetchMore, shouldFetchOnInit, loading, + renderBlankState, // Downshift props getInputProps, @@ -155,8 +180,26 @@ const DownshiftAutocompleteContent = ({ isOpen, inputValue, highlightedIndex, - toggleMenu -}: DownshiftAutocompleteContentProps) => { + toggleMenu, + clearItems, + clearSelection, + closeMenu, + getRootProps, + getToggleButtonProps, + openMenu, + reset, + selectHighlightedItem, + selectItem, + selectItemAtIndex, + selectedItem, + setHighlightedIndex, + setItemCount, + setState, + unsetItemCount, + + ...props +}: DownshiftAutocompleteContentProps & + React.DetailedHTMLProps, HTMLInputElement>) => { // I use ref instead of state for this, because I don't want it to trigger an effect or re-render. // I could simply not use it on the deps array, BUT then the value wouldn't be up to date inside the effect scope const isFetchingRef = useRef(false); @@ -213,7 +256,10 @@ const DownshiftAutocompleteContent = ({ {/* Render the combo container for the input and the results */}
!isOpen && toggleMenu()} /> {/* */} @@ -270,6 +316,8 @@ const DownshiftAutocompleteContent = ({ ); }) + ) : renderBlankState ? ( + renderBlankState(selectItem) ) : (
  • @@ -311,7 +359,8 @@ const DownshiftAutocompleteContent = ({ * @param props.loading Whether the options are loading */ export const AutocompleteInput = ( - props: AutocompleteInputProps + props: AutocompleteInputProps & + React.DetailedHTMLProps, HTMLInputElement> ) => { const { itemToString,