diff --git a/src/components/tags/suggestions-tag-input.tsx b/src/components/tags/suggestions-tag-input.tsx deleted file mode 100644 index decb1d444..000000000 --- a/src/components/tags/suggestions-tag-input.tsx +++ /dev/null @@ -1,266 +0,0 @@ -"use client"; - -import React, { useEffect, useRef, useState } from "react"; -import { type VariantProps } from "class-variance-authority"; -import { Check } from "lucide-react"; -import { useTranslations } from "next-intl"; -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList -} from "@app/components/ui/command"; -import { - Popover, - PopoverAnchor, - PopoverContent, - PopoverTrigger -} from "@app/components/ui/popover"; -import { Button } from "@app/components/ui/button"; -import { cn } from "@app/lib/cn"; -import { tagVariants } from "./tag"; -import { TagList } from "./tag-list"; -import type { Tag, TagInputStyleClassesProps } from "./tag-input"; - -export type SuggestionsTagInputProps = { - tags: Tag[]; - setTags: React.Dispatch>; - suggestedOptions: Tag[]; - searchQuery: string; - onSearchQueryChange: (value: string) => void; - activeTagIndex: number | null; - setActiveTagIndex: React.Dispatch>; - placeholder?: string; - maxTags?: number; - onTagAdd?: (tag: string) => void; - onTagRemove?: (tag: string) => void; - allowDuplicates?: boolean; - disabled?: boolean; - usePortal?: boolean; - styleClasses?: TagInputStyleClassesProps; -} & VariantProps; - -export function SuggestionsTagInput({ - tags, - setTags, - suggestedOptions, - searchQuery, - onSearchQueryChange, - activeTagIndex, - setActiveTagIndex, - placeholder, - maxTags, - onTagAdd, - onTagRemove, - allowDuplicates = false, - disabled = false, - usePortal = false, - styleClasses = {}, - variant, - size, - shape, - borderStyle, - textCase, - interaction, - animation, - textStyle -}: SuggestionsTagInputProps) { - const t = useTranslations(); - const triggerRef = useRef(null); - const popoverContentRef = useRef(null); - const [isOpen, setIsOpen] = useState(false); - const [popoverWidth, setPopoverWidth] = useState(0); - - useEffect(() => { - const handleOutsideClick = (event: MouseEvent | TouchEvent) => { - if ( - isOpen && - triggerRef.current && - popoverContentRef.current && - !triggerRef.current.contains(event.target as Node) && - !popoverContentRef.current.contains(event.target as Node) - ) { - setIsOpen(false); - } - }; - document.addEventListener("mousedown", handleOutsideClick); - return () => - document.removeEventListener("mousedown", handleOutsideClick); - }, [isOpen]); - - const handleOpenChange = (open: boolean) => { - if (open && triggerRef.current) { - setPopoverWidth(triggerRef.current.getBoundingClientRect().width); - } - if (open) setIsOpen(true); - }; - - const toggleTag = (option: Tag) => { - const index = tags.findIndex((tag) => tag.text === option.text); - if (index >= 0) { - setTags(tags.filter((_, i) => i !== index)); - onTagRemove?.(option.text); - } else { - if ( - !allowDuplicates && - tags.some((tag) => tag.text === option.text) - ) - return; - if (!maxTags || tags.length < maxTags) { - setTags([...tags, option]); - onTagAdd?.(option.text); - } - } - }; - - const removeTag = (idToRemove: string) => { - const removed = tags.find((tag) => tag.id === idToRemove); - setTags(tags.filter((tag) => tag.id !== idToRemove)); - if (removed) onTagRemove?.(removed.text); - }; - - const onSortEnd = (oldIndex: number, newIndex: number) => { - setTags((current) => { - const next = [...current]; - const [moved] = next.splice(oldIndex, 1); - next.splice(newIndex, 0, moved); - return next; - }); - }; - - return ( - - -
- - - - -
-
- - - - - {t("noResults")} - - {suggestedOptions.map((option) => { - const isChosen = tags.some( - (tag) => tag.text === option.text - ); - return ( - toggleTag(option)} - className={ - styleClasses?.autoComplete - ?.commandItem - } - > - - {option.text} - - ); - })} - - - - -
- ); -} diff --git a/src/components/tags/tag-input.tsx b/src/components/tags/tag-input.tsx index 3241912c5..1ea93b468 100644 --- a/src/components/tags/tag-input.tsx +++ b/src/components/tags/tag-input.tsx @@ -87,7 +87,6 @@ export interface TagInputProps onInputChange?: (value: string) => void; searchQuery?: string; onSearchQueryChange?: (value: string) => void; - autocompleteContent?: React.ReactNode; customTagRenderer?: (tag: Tag, isActiveTag: boolean) => React.ReactNode; onFocus?: React.FocusEventHandler; onBlur?: React.FocusEventHandler; @@ -162,8 +161,7 @@ export function TagInput({ ref, ...props }: TagInputProps) { addOnPaste = false, generateTagId = uuid, searchQuery, - onSearchQueryChange, - autocompleteContent + onSearchQueryChange } = props; const [inputValue, setInputValue] = React.useState(""); @@ -489,7 +487,7 @@ export function TagInput({ ref, ...props }: TagInputProps) { disabled={disabled} /> ) : ( - !enableAutocomplete && !autocompleteContent && ( + !enableAutocomplete && (
) ))} - {!enableAutocomplete && autocompleteContent && ( -
-
- - = maxTags - ? placeholderWhenFull - : placeholder - } - value={effectiveQuery} - onChange={handleInputChange} - onKeyDown={handleKeyDown} - onFocus={handleInputFocus} - onBlur={handleInputBlur} - {...inputProps} - className={cn( - "border-0 px-2 h-5 bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 flex-1 w-fit shadow-none inset-shadow-none", - styleClasses?.input - )} - autoComplete="off" - disabled={ - disabled || - (maxTags !== undefined && tags.length >= maxTags) - } - /> -
- {autocompleteContent} -
- )} + {enableAutocomplete ? (