Skip to content

Commit

Permalink
[@mantine/core] MultiSelect: Added controlled/uncontrolled search value
Browse files Browse the repository at this point in the history
  • Loading branch information
dipiash committed Sep 17, 2022
1 parent b50cc5d commit a733140
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 13 deletions.
30 changes: 17 additions & 13 deletions src/mantine-core/src/MultiSelect/MultiSelect.tsx
Expand Up @@ -65,6 +65,9 @@ export interface MultiSelectProps
/** Called each time search query changes */
onSearchChange?(query: string): void;

/** Controlled search input value */
searchValue?: string;

/** Allow creatable option */
creatable?: boolean;

Expand Down Expand Up @@ -177,6 +180,7 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
clearButtonLabel,
variant,
onSearchChange,
searchValue,
disabled,
initiallyOpened,
radius,
Expand Down Expand Up @@ -225,7 +229,12 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
const [dropdownOpened, _setDropdownOpened] = useState(initiallyOpened);
const [hovered, setHovered] = useState(-1);
const [direction, setDirection] = useState<React.CSSProperties['flexDirection']>('column');
const [searchValue, setSearchValue] = useState('');
const [_searchValue, handleSearchChange] = useUncontrolled({
value: searchValue,
defaultValue: '',
finalValue: undefined,
onChange: onSearchChange,
});
const [IMEOpen, setIMEOpen] = useState(false);

const { scrollIntoView, targetRef, scrollableRef } = useScrollIntoView({
Expand All @@ -244,11 +253,6 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
typeof handler === 'function' && handler();
};

const handleSearchChange = (val: string) => {
typeof onSearchChange === 'function' && onSearchChange(val);
setSearchValue(val);
};

const formattedData = data.map((item) =>
typeof item === 'string' ? { label: item, value: item } : item
);
Expand Down Expand Up @@ -288,7 +292,7 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
const filteredData = filterData({
data: sortedData,
searchable,
searchValue,
searchValue: _searchValue,
limit,
filter,
value: _value,
Expand All @@ -309,7 +313,7 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props

useDidUpdate(() => {
setHovered(-1);
}, [searchValue]);
}, [_searchValue]);

useDidUpdate(() => {
if (!disabled && _value.length > data.length) {
Expand Down Expand Up @@ -472,7 +476,7 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
}

case 'Backspace': {
if (_value.length > 0 && searchValue.length === 0) {
if (_value.length > 0 && _searchValue.length === 0) {
setValue(_value.slice(0, -1));
setDropdownOpened(true);
if (maxSelectedValues) {
Expand Down Expand Up @@ -563,9 +567,9 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
}
};

if (isCreatable && shouldCreate(searchValue, sortedData)) {
createLabel = getCreateLabel(searchValue);
filteredData.push({ label: searchValue, value: searchValue, creatable: true });
if (isCreatable && shouldCreate(_searchValue, sortedData)) {
createLabel = getCreateLabel(_searchValue);
filteredData.push({ label: _searchValue, value: _searchValue, creatable: true });
}

const shouldRenderDropdown =
Expand Down Expand Up @@ -682,7 +686,7 @@ export const MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>((props
[classes.searchInputEmpty]: _value.length === 0,
})}
onKeyDown={handleInputKeydown}
value={searchValue}
value={_searchValue}
onChange={handleInputChange}
onFocus={handleInputFocus}
onBlur={handleInputBlur}
Expand Down
@@ -0,0 +1,47 @@
import React, { useState } from 'react';
import { MultiSelect } from '@mantine/core';
import { data } from './_data';

const code = `
import { MultiSelect } from '@mantine/core';
function Demo() {
const [searchValue, onSearchChange] = useState('');
return (
<MultiSelect
data={['React', 'Angular', 'Svelte', 'Vue', 'Riot', 'Next.js', 'Blitz.js']}
label="Your favorite frameworks/libraries"
placeholder="Pick all that you like"
searchable
searchValue={searchValue}
onSearchChange={onSearchChange}
nothingFound="Nothing found"
/>
);
}
`;

function Demo() {
const [searchValue, onSearchChange] = useState('');

return (
<div style={{ maxWidth: 400, marginLeft: 'auto', marginRight: 'auto' }}>
<MultiSelect
data={data}
label="Your favorite frameworks/libraries"
placeholder="Pick all that you like"
searchable
searchValue={searchValue}
onSearchChange={onSearchChange}
nothingFound="Nothing found"
/>
</div>
);
}

export const searchableControlled: MantineDemo = {
type: 'demo',
code,
component: Demo,
};
1 change: 1 addition & 0 deletions src/mantine-demos/src/demos/core/MultiSelect/index.ts
@@ -1,6 +1,7 @@
export { countries } from './MultiSelect.demo.countries';
export { usage } from './MultiSelect.demo.usage';
export { searchable } from './MultiSelect.demo.searchable';
export { searchableControlled } from './MultiSelect.demo.searchableControlled';
export { clearable } from './MultiSelect.demo.clearable';
export { configurator } from './MultiSelect.demo.configurator';
export { flip } from './MultiSelect.demo.flip';
Expand Down

0 comments on commit a733140

Please sign in to comment.