Make sure suggestions are selectable in TagsSelector

This commit is contained in:
Alejandro Celaya 2023-08-12 19:51:18 +02:00
parent e4aec16ba5
commit 5b15c184eb
2 changed files with 9 additions and 8 deletions

View file

@ -1,4 +1,4 @@
import resolveClasses from 'classnames'; import classNames from 'classnames';
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import type { OptionRendererProps, ReactTagsAPI, TagRendererProps, TagSuggestion } from 'react-tag-autocomplete'; import type { OptionRendererProps, ReactTagsAPI, TagRendererProps, TagSuggestion } from 'react-tag-autocomplete';
import { ReactTags } from 'react-tag-autocomplete'; import { ReactTags } from 'react-tag-autocomplete';
@ -25,7 +25,7 @@ const NOT_FOUND_TAG = 'Tag not found';
const NEW_TAG = 'Add tag'; const NEW_TAG = 'Add tag';
const isSelectableOption = (tag: string) => tag !== NOT_FOUND_TAG; const isSelectableOption = (tag: string) => tag !== NOT_FOUND_TAG;
const isNewOption = (tag: string) => tag === NEW_TAG; const isNewOption = (tag: string) => tag === NEW_TAG;
const toTagSuggestion = (tag: string): TagSuggestion => ({ label: tag, value: tag }); const toTagObject = (tag: string): TagSuggestion => ({ label: tag, value: tag });
export const TagsSelector = (colorGenerator: ColorGenerator) => ( export const TagsSelector = (colorGenerator: ColorGenerator) => (
{ selectedTags, onChange, placeholder, listTags, tagsList, allowNew = true }: TagsSelectorConnectProps, { selectedTags, onChange, placeholder, listTags, tagsList, allowNew = true }: TagsSelectorConnectProps,
@ -41,16 +41,17 @@ export const TagsSelector = (colorGenerator: ColorGenerator) => (
const ReactTagsTag = ({ tag, onClick: deleteTag }: TagRendererProps) => ( const ReactTagsTag = ({ tag, onClick: deleteTag }: TagRendererProps) => (
<Tag colorGenerator={colorGenerator} text={tag.label} clearable className="react-tags__tag" onClose={deleteTag} /> <Tag colorGenerator={colorGenerator} text={tag.label} clearable className="react-tags__tag" onClose={deleteTag} />
); );
const ReactTagsSuggestion = ({ option, classNames }: OptionRendererProps) => { const ReactTagsSuggestion = ({ option, classNames: classes, ...rest }: OptionRendererProps) => {
const isSelectable = isSelectableOption(option.label); const isSelectable = isSelectableOption(option.label);
const isNew = isNewOption(option.label); const isNew = isNewOption(option.label);
return ( return (
<div <div
className={resolveClasses(classNames.option, { className={classNames(classes.option, {
[classNames.optionIsActive]: isSelectable && option.active, [classes.optionIsActive]: isSelectable && option.active,
'react-tags__listbox-option--not-selectable': !isSelectable, 'react-tags__listbox-option--not-selectable': !isSelectable,
})} })}
{...rest}
> >
{!isSelectable ? <i>{option.label}</i> : ( {!isSelectable ? <i>{option.label}</i> : (
<> <>
@ -65,8 +66,8 @@ export const TagsSelector = (colorGenerator: ColorGenerator) => (
return ( return (
<ReactTags <ReactTags
ref={apiRef} ref={apiRef}
selected={selectedTags.map(toTagSuggestion)} selected={selectedTags.map(toTagObject)}
suggestions={tagsList.tags.filter((tag) => !selectedTags.includes(tag)).map(toTagSuggestion)} suggestions={tagsList.tags.filter((tag) => !selectedTags.includes(tag)).map(toTagObject)}
renderTag={ReactTagsTag} renderTag={ReactTagsTag}
renderOption={ReactTagsSuggestion} renderOption={ReactTagsSuggestion}
activateFirstOption activateFirstOption

View file

@ -42,7 +42,7 @@ describe('<TagsSelector />', () => {
await user.type(screen.getByPlaceholderText('Add tags to the URL'), 'ba'); await user.type(screen.getByPlaceholderText('Add tags to the URL'), 'ba');
expect(container.querySelector('.react-tags__suggestions')).toBeInTheDocument(); expect(container.querySelector('.react-tags__combobox')).toBeInTheDocument();
expect(screen.getByText('baz')).toBeInTheDocument(); expect(screen.getByText('baz')).toBeInTheDocument();
}); });