Skip to content

Commit

Permalink
feat(autocomplete): Possible solution for object-checking (#3455)
Browse files Browse the repository at this point in the history
References issue #3259
  • Loading branch information
yusijs committed May 23, 2024
1 parent a03050c commit 13336b4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,25 @@ export const OptionComponent: StoryFn<AutocompleteProps<MyOptionType>> = (
options={options}
optionLabel={(opt) => `${opt.trend} ${opt.label} (${opt.symbol})`}
optionComponent={CustomItem}
initialSelectedOptions={[options[1]]}
initialSelectedOptions={
[JSON.parse(JSON.stringify(options[1]))] as MyOptionType[]
}
itemCompare={(item, compare) => {
return item.label === compare.label
}}
multiline
/>
<Autocomplete
label="Select multiple stocks"
options={options}
optionLabel={(opt) => `${opt.trend} ${opt.label} (${opt.symbol})`}
optionComponent={CustomItem}
initialSelectedOptions={[options[1]]}
initialSelectedOptions={
JSON.parse(JSON.stringify([options[1], options[2]])) as MyOptionType[]
}
itemCompare={(item, compare) => {
return item.label === compare.label
}}
multiline
multiple
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ const handleListFocus = (e: FocusEvent<HTMLElement>) => {

const defaultOptionDisabled = () => false

type OptionLabelProps<T> = T extends string | number
// prettier-ignore
type OptionLabelProps<T,> = T extends string | number
? {
/** Custom option label */
optionLabel?: (option: T) => string
Expand Down Expand Up @@ -325,6 +326,10 @@ export type AutocompleteProps<T> = {
* @default 300
*/
dropdownHeight?: number
/**
* Method that is used to compare objects by value. If omitted, objects are matched by reference.
*/
itemCompare?: (value: T, compare: T) => boolean
} & HTMLAttributes<HTMLDivElement> &
OptionLabelProps<T>

Expand All @@ -344,10 +349,11 @@ function AutocompleteInner<T>(
hideClearButton = false,
onOptionsChange,
onInputChange,
selectedOptions,
selectedOptions: _selectedOptions,
multiple,
itemCompare,
allowSelectAll,
initialSelectedOptions = [],
initialSelectedOptions: _initialSelectedOptions = [],
disablePortal,
optionDisabled = defaultOptionDisabled,
optionsFilter,
Expand All @@ -365,6 +371,21 @@ function AutocompleteInner<T>(
...other
} = props

const selectedOptions = _selectedOptions
? itemCompare
? options.filter((item) =>
_selectedOptions.some((compare) => itemCompare(item, compare)),
)
: _selectedOptions
: undefined
const initialSelectedOptions = _initialSelectedOptions
? itemCompare
? options.filter((item) =>
_initialSelectedOptions.some((compare) => itemCompare(item, compare)),
)
: _initialSelectedOptions
: undefined

if (disablePortal) {
console.warn(
'Autocomplete "disablePortal" prop has been deprecated. Autocomplete now uses the native popover api',
Expand Down Expand Up @@ -423,9 +444,14 @@ function AutocompleteInner<T>(
...multipleSelectionProps,
onSelectedItemsChange: (changes) => {
if (onOptionsChange) {
const selectedItems = changes.selectedItems.filter(
let selectedItems = changes.selectedItems.filter(
(item) => item !== AllSymbol,
)
if (itemCompare) {
selectedItems = inputOptions.filter((item) =>
selectedItems.some((compare) => itemCompare(item, compare)),
)
}
onOptionsChange({ selectedItems })
}
},
Expand Down Expand Up @@ -607,7 +633,12 @@ function AutocompleteInner<T>(
...comboBoxProps,
onSelectedItemChange: (changes) => {
if (onOptionsChange) {
const { selectedItem } = changes
let { selectedItem } = changes
if (itemCompare) {
selectedItem = inputOptions.find((item) =>
itemCompare(item, selectedItem),
)
}
onOptionsChange({
selectedItems: selectedItem ? [selectedItem] : [],
})
Expand Down

0 comments on commit 13336b4

Please sign in to comment.