Merge pull request #5923 from tchak/improuve-multi-select

Improuve multi select
This commit is contained in:
Paul Chavard 2021-02-19 11:15:02 +01:00 committed by GitHub
commit 1745f58496
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -31,23 +31,46 @@ function ComboMultipleDropdownList({
if (label == undefined) { if (label == undefined) {
label = 'Choisir une option'; label = 'Choisir une option';
} }
if (Array.isArray(options[0]) == false) { if (!Array.isArray(options[0])) {
options = options.map((o) => [o, o]); options = options.filter((o) => o).map((o) => [o, o]);
} }
const inputRef = useRef(); const inputRef = useRef();
const [term, setTerm] = useState(''); const [term, setTerm] = useState('');
const [selections, setSelections] = useState(selected); const [selections, setSelections] = useState(selected);
const [newValues, setNewValues] = useState([]); const [newValues, setNewValues] = useState([]);
const optionValueByLabel = (label) => {
const maybeOption = newValues.includes(label)
? [label, label]
: options.find(([optionLabel]) => optionLabel == label);
return maybeOption ? maybeOption[1] : undefined;
};
const optionLabelByValue = (value) => {
const maybeOption = newValues.includes(value)
? [value, value]
: options.find(([, optionValue]) => optionValue == value);
return maybeOption ? maybeOption[0] : undefined;
};
const extraOptions = useMemo(
() =>
acceptNewValues && term && term.length > 2 && !optionLabelByValue(term)
? [[term, term]]
: [],
[acceptNewValues, term, newValues.join(',')]
);
const results = useMemo( const results = useMemo(
() => () =>
(term [
? matchSorter( ...extraOptions,
options.filter((o) => !o[0].startsWith('--')), ...(term
term ? matchSorter(
) options.filter(([label]) => !label.startsWith('--')),
: options term
).filter((o) => o[0] && !selections.includes(o[1])), )
[term, selections.join(',')] : options)
].filter(([, value]) => !selections.includes(value)),
[term, selections.join(','), newValues.join(',')]
); );
const hiddenField = useMemo( const hiddenField = useMemo(
() => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`), () => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`),
@ -60,22 +83,12 @@ function ComboMultipleDropdownList({
const onKeyDown = (event) => { const onKeyDown = (event) => {
if (event.key === 'Enter') { if (event.key === 'Enter') {
if (term && options.map((o) => o[0]).includes(term)) {
event.preventDefault();
return onSelect(term);
}
if ( if (
acceptNewValues &&
term && term &&
matchSorter( [...extraOptions, ...options].map(([label]) => label).includes(term)
options.map((o) => o[0]),
term
).length == 0 // ignore when was pressed for selecting popover option
) { ) {
event.preventDefault(); event.preventDefault();
setNewValues([...newValues, term]); return onSelect(term);
saveSelection([...selections, term]);
setTerm('');
} }
} }
}; };
@ -89,19 +102,23 @@ function ComboMultipleDropdownList({
}; };
const onSelect = (value) => { const onSelect = (value) => {
let sel = options.find((o) => o[0] == value)[1]; const maybeValue = [...extraOptions, ...options].find(
saveSelection([...selections, sel]); ([val]) => val == value
);
const selectedValue = maybeValue && maybeValue[1];
if (value) {
setNewValues([...newValues, selectedValue]);
saveSelection([...selections, selectedValue]);
}
setTerm(''); setTerm('');
}; };
const onRemove = (value) => { const onRemove = (label) => {
saveSelection( const optionValue = optionValueByLabel(label);
selections.filter((s) => if (optionValue) {
newValues.includes(value) saveSelection(selections.filter((value) => value != optionValue));
? s != value setNewValues(newValues.filter((value) => value != optionValue));
: s !== options.find((o) => o[0] == value)[1] }
)
);
inputRef.current.focus(); inputRef.current.focus();
}; };
@ -116,10 +133,7 @@ function ComboMultipleDropdownList({
{selections.map((selection) => ( {selections.map((selection) => (
<ComboboxToken <ComboboxToken
key={selection} key={selection}
value={ value={optionLabelByValue(selection)}
newValues.find((newValue) => newValue == selection) ||
options.find((o) => o[1] == selection)[0]
}
/> />
))} ))}
</ul> </ul>
@ -136,21 +150,15 @@ function ComboMultipleDropdownList({
{results.length === 0 && ( {results.length === 0 && (
<p> <p>
Aucun résultat{' '} Aucun résultat{' '}
<button <button onClick={() => setTerm('')}>Effacer</button>
onClick={() => {
setTerm('');
}}
>
Effacer
</button>
</p> </p>
)} )}
<ComboboxList> <ComboboxList>
{results.map((value, index) => { {results.map(([label], index) => {
if (value[0].startsWith('--')) { if (label.startsWith('--')) {
return <ComboboxSeparator key={index} value={value[0]} />; return <ComboboxSeparator key={index} value={label} />;
} }
return <ComboboxOption key={index} value={value[0]} />; return <ComboboxOption key={index} value={label} />;
})} })}
</ComboboxList> </ComboboxList>
</ComboboxPopover> </ComboboxPopover>