Allow pasting of multiple tags

This commit is contained in:
Sam Becker 2024-03-03 12:44:57 -06:00
parent 16b107c252
commit 57a4c17d0f

View File

@ -67,18 +67,22 @@ export default function TagInput({
}
}, []);
const addOption = useCallback((option?: string) => {
if (option && !selectedOptions.includes(option)) {
const addOptions = useCallback((options: (string | undefined)[]) => {
const optionsToAdd = (options
.filter(Boolean) as string[])
.map(option => option.startsWith(CREATE_LABEL)
? option.match(new RegExp(`^${CREATE_LABEL} "(.+)"$`))?.[1] ?? option
: option)
.map(option => parameterize(option))
.filter(option => !selectedOptions.includes(option));
if (optionsToAdd.length > 0) {
onChange?.([
...selectedOptions,
option.startsWith(CREATE_LABEL)
? option.match(new RegExp(`^${CREATE_LABEL} "(.+)"$`))?.[1] ?? option
: option,
]
.filter(Boolean)
.map(item => parameterize(item))
.join(','));
...optionsToAdd,
].join(','));
}
setSelectedOptionIndex(undefined);
inputRef.current?.focus();
}, [onChange, selectedOptions]);
@ -93,9 +97,14 @@ export default function TagInput({
// Show options when input text changes
useEffect(() => {
if (inputText) {
setShouldShowMenu(true);
if (inputText.includes(',')) {
addOptions(inputText.split(','));
setInputText('');
} else {
setShouldShowMenu(true);
}
}
}, [inputText]);
}, [inputText, addOptions, selectedOptions]);
// Focus option in the DOM when selected index changes
useEffect(() => {
@ -113,7 +122,6 @@ export default function TagInput({
const listener = (e: KeyboardEvent) => {
// Keys which always trap focus
switch (e.key) {
case ',':
case 'ArrowDown':
case 'ArrowUp':
case 'Escape':
@ -127,14 +135,10 @@ export default function TagInput({
if (shouldShowMenu && optionsFiltered.length > 0) {
e.stopImmediatePropagation();
e.preventDefault();
addOption(optionsFiltered[selectedOptionIndex ?? 0].value);
addOptions([optionsFiltered[selectedOptionIndex ?? 0].value]);
setInputText('');
}
break;
case ',':
addOption(inputText);
setInputText('');
break;
case 'ArrowDown':
if (shouldShowMenu) {
setSelectedOptionIndex(i => {
@ -187,7 +191,7 @@ export default function TagInput({
selectedOptions,
selectedOptionIndex,
optionsFiltered,
addOption,
addOptions,
shouldShowMenu,
]);
@ -304,7 +308,7 @@ export default function TagInput({
'outline-none',
)}
onClick={() => {
addOption(value);
addOptions([value]);
setInputText('');
}}
onFocus={() => setSelectedOptionIndex(index)}