{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tag",
  "type": "registry:component",
  "title": "Tag Components",
  "description": "A collection of tag-related components including Tag, TagInput, TagList, TagPopover, and Autocomplete.",
  "dependencies": ["tailwindcss@^4"],
  "registryDependencies": ["button", "input", "popover"],
  "files": [
    {
      "path": "registry/default/components/tag.tsx",
      "content": "import React from 'react';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/registry/default/lib/utils';\nimport { TagInputProps, TagInputStyleClassesProps, type Tag as TagType } from './tag-input';\n\nimport { cva } from 'class-variance-authority';\n\nexport const tagVariants = cva('transition-all border inline-flex items-center text-sm pl-2 rounded-md', {\n  variants: {\n    variant: {\n      default:\n        'bg-secondary text-secondary-foreground hover:bg-secondary/80 disabled:cursor-not-allowed disabled:opacity-50',\n      primary:\n        'bg-primary border-primary text-primary-foreground hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50',\n      destructive:\n        'bg-destructive border-destructive text-destructive-foreground hover:bg-destructive/90 disabled:cursor-not-allowed disabled:opacity-50',\n    },\n    size: {\n      sm: 'text-xs h-7',\n      md: 'text-sm h-8',\n      lg: 'text-base h-9',\n      xl: 'text-lg h-10',\n    },\n    shape: {\n      default: 'rounded-sm',\n      rounded: 'rounded-lg',\n      square: 'rounded-none',\n      pill: 'rounded-full',\n    },\n    borderStyle: {\n      default: 'border-solid',\n      none: 'border-none',\n      dashed: 'border-dashed',\n      dotted: 'border-dotted',\n      double: 'border-double',\n    },\n    textCase: {\n      uppercase: 'uppercase',\n      lowercase: 'lowercase',\n      capitalize: 'capitalize',\n    },\n    interaction: {\n      clickable: 'cursor-pointer hover:shadow-md',\n      nonClickable: 'cursor-default',\n    },\n    animation: {\n      none: '',\n      fadeIn: 'animate-fadeIn',\n      slideIn: 'animate-slideIn',\n      bounce: 'animate-bounce',\n    },\n    textStyle: {\n      normal: 'font-normal',\n      bold: 'font-bold',\n      italic: 'italic',\n      underline: 'underline',\n      lineThrough: 'line-through',\n    },\n  },\n  defaultVariants: {\n    variant: 'default',\n    size: 'md',\n    shape: 'default',\n    borderStyle: 'default',\n    interaction: 'nonClickable',\n    animation: 'fadeIn',\n    textStyle: 'normal',\n  },\n});\n\nexport type TagProps = {\n  tagObj: TagType;\n  variant: TagInputProps['variant'];\n  size: TagInputProps['size'];\n  shape: TagInputProps['shape'];\n  borderStyle: TagInputProps['borderStyle'];\n  textCase: TagInputProps['textCase'];\n  interaction: TagInputProps['interaction'];\n  animation: TagInputProps['animation'];\n  textStyle: TagInputProps['textStyle'];\n  onRemoveTag: (id: string) => void;\n  isActiveTag?: boolean;\n  tagClasses?: TagInputStyleClassesProps['tag'];\n  disabled?: boolean;\n} & Pick<TagInputProps, 'direction' | 'onTagClick' | 'draggable'>;\n\nexport const Tag: React.FC<TagProps> = ({\n  tagObj,\n  direction,\n  draggable,\n  onTagClick,\n  onRemoveTag,\n  variant,\n  size,\n  shape,\n  borderStyle,\n  textCase,\n  interaction,\n  animation,\n  textStyle,\n  isActiveTag,\n  tagClasses,\n  disabled,\n}) => {\n  return (\n    <span\n      key={tagObj.id}\n      draggable={draggable}\n      className={cn(\n        tagVariants({\n          variant,\n          size,\n          shape,\n          borderStyle,\n          textCase,\n          interaction,\n          animation,\n          textStyle,\n        }),\n        {\n          'justify-between w-full': direction === 'column',\n          'cursor-pointer': draggable,\n          'ring-ring ring-offset-2 ring-2 ring-offset-background': isActiveTag,\n        },\n        tagClasses?.body,\n      )}\n      onClick={() => onTagClick?.(tagObj)}\n    >\n      {tagObj.text}\n      <Button\n        type=\"button\"\n        variant=\"ghost\"\n        onClick={(e) => {\n          e.stopPropagation(); // Prevent event from bubbling up to the tag span\n          onRemoveTag(tagObj.id);\n        }}\n        disabled={disabled}\n        className={cn(`py-1 px-3 h-full hover:bg-transparent`, tagClasses?.closeButton)}\n      >\n        <svg\n          xmlns=\"http://www.w3.org/2000/svg\"\n          width=\"14\"\n          height=\"14\"\n          viewBox=\"0 0 24 24\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"2\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          className=\"lucide lucide-x\"\n        >\n          <path d=\"M18 6 6 18\"></path>\n          <path d=\"m6 6 12 12\"></path>\n        </svg>\n      </Button>\n    </span>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "registry/default/components/tag-input.tsx",
      "content": "'use client';\n\nimport React, { useMemo } from 'react';\nimport { Input } from '@/components/ui/input';\nimport { Button } from '@/components/ui/button';\nimport { type VariantProps } from 'class-variance-authority';\n// import { CommandInput } from '../ui/command';\nimport { TagPopover } from '@/registry/default/components/tag-popover';\nimport { TagList } from '@/registry/default/components/tag-list';\nimport { tagVariants } from '@/registry/default/components/tag';\nimport { Autocomplete } from '@/registry/default/components/tag-autocomplete';\nimport { cn, uuid } from '@/registry/default/lib/utils';\n\nexport enum Delimiter {\n  Comma = ',',\n  Enter = 'Enter',\n}\n\ntype OmittedInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'value'>;\n\nexport type Tag = {\n  id: string;\n  text: string;\n};\n\nexport interface TagInputStyleClassesProps {\n  inlineTagsContainer?: string;\n  tagPopover?: {\n    popoverTrigger?: string;\n    popoverContent?: string;\n  };\n  tagList?: {\n    container?: string;\n    sortableList?: string;\n  };\n  autoComplete?: {\n    command?: string;\n    popoverTrigger?: string;\n    popoverContent?: string;\n    commandList?: string;\n    commandGroup?: string;\n    commandItem?: string;\n  };\n  tag?: {\n    body?: string;\n    closeButton?: string;\n  };\n  input?: string;\n  clearAllButton?: string;\n}\n\nexport interface TagInputProps extends OmittedInputProps, VariantProps<typeof tagVariants> {\n  placeholder?: string;\n  tags: Tag[];\n  setTags: React.Dispatch<React.SetStateAction<Tag[]>>;\n  enableAutocomplete?: boolean;\n  autocompleteOptions?: Tag[];\n  maxTags?: number;\n  minTags?: number;\n  readOnly?: boolean;\n  disabled?: boolean;\n  onTagAdd?: (tag: string) => void;\n  onTagRemove?: (tag: string) => void;\n  allowDuplicates?: boolean;\n  validateTag?: (tag: string) => boolean;\n  delimiter?: Delimiter;\n  showCount?: boolean;\n  placeholderWhenFull?: string;\n  sortTags?: boolean;\n  delimiterList?: string[];\n  truncate?: number;\n  minLength?: number;\n  maxLength?: number;\n  usePopoverForTags?: boolean;\n  value?: string | number | readonly string[] | { id: string; text: string }[];\n  autocompleteFilter?: (option: string) => boolean;\n  direction?: 'row' | 'column';\n  onInputChange?: (value: string) => void;\n  customTagRenderer?: (tag: Tag, isActiveTag: boolean) => React.ReactNode;\n  onFocus?: React.FocusEventHandler<HTMLInputElement>;\n  onBlur?: React.FocusEventHandler<HTMLInputElement>;\n  onTagClick?: (tag: Tag) => void;\n  draggable?: boolean;\n  inputFieldPosition?: 'bottom' | 'top';\n  clearAll?: boolean;\n  onClearAll?: () => void;\n  inputProps?: React.InputHTMLAttributes<HTMLInputElement>;\n  restrictTagsToAutocompleteOptions?: boolean;\n  inlineTags?: boolean;\n  activeTagIndex: number | null;\n  setActiveTagIndex: React.Dispatch<React.SetStateAction<number | null>>;\n  styleClasses?: TagInputStyleClassesProps;\n  usePortal?: boolean;\n  addOnPaste?: boolean;\n  addTagsOnBlur?: boolean;\n  generateTagId?: () => string;\n}\n\nconst TagInput = React.forwardRef<HTMLInputElement, TagInputProps>((props, ref) => {\n  const {\n    id,\n    placeholder,\n    tags,\n    setTags,\n    variant,\n    size,\n    shape,\n    enableAutocomplete,\n    autocompleteOptions,\n    maxTags,\n    delimiter = Delimiter.Comma,\n    onTagAdd,\n    onTagRemove,\n    allowDuplicates,\n    showCount,\n    validateTag,\n    placeholderWhenFull = 'Max tags reached',\n    sortTags,\n    delimiterList,\n    truncate,\n    autocompleteFilter,\n    borderStyle,\n    textCase,\n    interaction,\n    animation,\n    textStyle,\n    minLength,\n    maxLength,\n    direction = 'row',\n    onInputChange,\n    customTagRenderer,\n    onFocus,\n    onBlur,\n    onTagClick,\n    draggable = false,\n    inputFieldPosition = 'bottom',\n    clearAll = false,\n    onClearAll,\n    usePopoverForTags = false,\n    inputProps = {},\n    restrictTagsToAutocompleteOptions,\n    inlineTags = true,\n    addTagsOnBlur = false,\n    activeTagIndex,\n    setActiveTagIndex,\n    styleClasses = {},\n    disabled = false,\n    usePortal = false,\n    addOnPaste = false,\n    generateTagId = uuid,\n  } = props;\n\n  const [inputValue, setInputValue] = React.useState('');\n  const [tagCount, setTagCount] = React.useState(Math.max(0, tags.length));\n  const inputRef = React.useRef<HTMLInputElement>(null);\n\n  if ((maxTags !== undefined && maxTags < 0) || (props.minTags !== undefined && props.minTags < 0)) {\n    console.warn('maxTags and minTags cannot be less than 0');\n    // error\n    return null;\n  }\n\n  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const newValue = e.target.value;\n    if (addOnPaste && newValue.includes(delimiter)) {\n      const splitValues = newValue\n        .split(delimiter)\n        .map((v) => v.trim())\n        .filter((v) => v);\n      splitValues.forEach((value) => {\n        if (!value) return; // Skip empty strings from split\n\n        const newTagText = value.trim();\n\n        // Check if the tag is in the autocomplete options if restrictTagsToAutocomplete is true\n        if (restrictTagsToAutocompleteOptions && !autocompleteOptions?.some((option) => option.text === newTagText)) {\n          console.warn('Tag not allowed as per autocomplete options');\n          return;\n        }\n\n        if (validateTag && !validateTag(newTagText)) {\n          console.warn('Invalid tag as per validateTag');\n          return;\n        }\n\n        if (minLength && newTagText.length < minLength) {\n          console.warn(`Tag \"${newTagText}\" is too short`);\n          return;\n        }\n\n        if (maxLength && newTagText.length > maxLength) {\n          console.warn(`Tag \"${newTagText}\" is too long`);\n          return;\n        }\n\n        const newTagId = generateTagId();\n\n        // Add tag if duplicates are allowed or tag does not already exist\n        if (allowDuplicates || !tags.some((tag) => tag.text === newTagText)) {\n          if (maxTags === undefined || tags.length < maxTags) {\n            // Check for maxTags limit\n            const newTag = { id: newTagId, text: newTagText };\n            setTags((prevTags) => [...prevTags, newTag]);\n            onTagAdd?.(newTagText);\n          } else {\n            console.warn('Reached the maximum number of tags allowed');\n          }\n        } else {\n          console.warn(`Duplicate tag \"${newTagText}\" not added`);\n        }\n      });\n      setInputValue('');\n    } else {\n      setInputValue(newValue);\n    }\n    onInputChange?.(newValue);\n  };\n\n  const handleInputFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n    setActiveTagIndex(null); // Reset active tag index when the input field gains focus\n    onFocus?.(event);\n  };\n\n  const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n    if (addTagsOnBlur && inputValue.trim()) {\n      const newTagText = inputValue.trim();\n\n      if (validateTag && !validateTag(newTagText)) {\n        return;\n      }\n\n      if (minLength && newTagText.length < minLength) {\n        console.warn('Tag is too short');\n        return;\n      }\n\n      if (maxLength && newTagText.length > maxLength) {\n        console.warn('Tag is too long');\n        return;\n      }\n\n      if (\n        (allowDuplicates || !tags.some((tag) => tag.text === newTagText)) &&\n        (maxTags === undefined || tags.length < maxTags)\n      ) {\n        const newTagId = generateTagId();\n        setTags([...tags, { id: newTagId, text: newTagText }]);\n        onTagAdd?.(newTagText);\n        setTagCount((prevTagCount) => prevTagCount + 1);\n        setInputValue('');\n      }\n    }\n\n    onBlur?.(event);\n  };\n\n  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n    if (delimiterList ? delimiterList.includes(e.key) : e.key === delimiter || e.key === Delimiter.Enter) {\n      e.preventDefault();\n      const newTagText = inputValue.trim();\n\n      // Check if the tag is in the autocomplete options if restrictTagsToAutocomplete is true\n      if (restrictTagsToAutocompleteOptions && !autocompleteOptions?.some((option) => option.text === newTagText)) {\n        // error\n        return;\n      }\n\n      if (validateTag && !validateTag(newTagText)) {\n        return;\n      }\n\n      if (minLength && newTagText.length < minLength) {\n        console.warn('Tag is too short');\n        // error\n        return;\n      }\n\n      // Validate maxLength\n      if (maxLength && newTagText.length > maxLength) {\n        // error\n        console.warn('Tag is too long');\n        return;\n      }\n\n      const newTagId = generateTagId();\n\n      if (\n        newTagText &&\n        (allowDuplicates || !tags.some((tag) => tag.text === newTagText)) &&\n        (maxTags === undefined || tags.length < maxTags)\n      ) {\n        setTags([...tags, { id: newTagId, text: newTagText }]);\n        onTagAdd?.(newTagText);\n        setTagCount((prevTagCount) => prevTagCount + 1);\n      }\n      setInputValue('');\n    } else {\n      switch (e.key) {\n        case 'Delete':\n          if (activeTagIndex !== null) {\n            e.preventDefault();\n            const newTags = [...tags];\n            newTags.splice(activeTagIndex, 1);\n            setTags(newTags);\n            setActiveTagIndex((prev) =>\n              newTags.length === 0 ? null : prev! >= newTags.length ? newTags.length - 1 : prev,\n            );\n            setTagCount((prevTagCount) => prevTagCount - 1);\n            onTagRemove?.(tags[activeTagIndex].text);\n          }\n          break;\n        case 'Backspace':\n          if (activeTagIndex !== null) {\n            e.preventDefault();\n            const newTags = [...tags];\n            newTags.splice(activeTagIndex, 1);\n            setTags(newTags);\n            setActiveTagIndex((prev) => (prev! === 0 ? null : prev! - 1));\n            setTagCount((prevTagCount) => prevTagCount - 1);\n            onTagRemove?.(tags[activeTagIndex].text);\n          }\n          break;\n        case 'ArrowRight':\n          e.preventDefault();\n          if (activeTagIndex === null) {\n            setActiveTagIndex(0);\n          } else {\n            setActiveTagIndex((prev) => (prev! + 1 >= tags.length ? 0 : prev! + 1));\n          }\n          break;\n        case 'ArrowLeft':\n          e.preventDefault();\n          if (activeTagIndex === null) {\n            setActiveTagIndex(tags.length - 1);\n          } else {\n            setActiveTagIndex((prev) => (prev! === 0 ? tags.length - 1 : prev! - 1));\n          }\n          break;\n        case 'Home':\n          e.preventDefault();\n          setActiveTagIndex(0);\n          break;\n        case 'End':\n          e.preventDefault();\n          setActiveTagIndex(tags.length - 1);\n          break;\n      }\n    }\n  };\n\n  const removeTag = (idToRemove: string) => {\n    setTags(tags.filter((tag) => tag.id !== idToRemove));\n    onTagRemove?.(tags.find((tag) => tag.id === idToRemove)?.text || '');\n    setTagCount((prevTagCount) => prevTagCount - 1);\n  };\n\n  const onSortEnd = (oldIndex: number, newIndex: number) => {\n    setTags((currentTags) => {\n      const newTags = [...currentTags];\n      const [removedTag] = newTags.splice(oldIndex, 1);\n      newTags.splice(newIndex, 0, removedTag);\n\n      return newTags;\n    });\n  };\n\n  const handleClearAll = () => {\n    if (!onClearAll) {\n      setActiveTagIndex(-1);\n      setTags([]);\n      return;\n    }\n    onClearAll?.();\n  };\n\n  // const filteredAutocompleteOptions = autocompleteFilter\n  //   ? autocompleteOptions?.filter((option) => autocompleteFilter(option.text))\n  //   : autocompleteOptions;\n  const filteredAutocompleteOptions = useMemo(() => {\n    return (autocompleteOptions || []).filter((option) =>\n      option.text.toLowerCase().includes(inputValue ? inputValue.toLowerCase() : ''),\n    );\n  }, [inputValue, autocompleteOptions]);\n\n  const displayedTags = sortTags ? [...tags].sort() : tags;\n\n  const truncatedTags = truncate\n    ? tags.map((tag) => ({\n        id: tag.id,\n        text: tag.text?.length > truncate ? `${tag.text.substring(0, truncate)}...` : tag.text,\n      }))\n    : displayedTags;\n\n  return (\n    <div\n      className={`w-full flex ${!inlineTags && tags.length > 0 ? 'gap-3' : ''} ${\n        inputFieldPosition === 'bottom' ? 'flex-col' : inputFieldPosition === 'top' ? 'flex-col-reverse' : 'flex-row'\n      }`}\n    >\n      {!usePopoverForTags &&\n        (!inlineTags ? (\n          <TagList\n            tags={truncatedTags}\n            customTagRenderer={customTagRenderer}\n            variant={variant}\n            size={size}\n            shape={shape}\n            borderStyle={borderStyle}\n            textCase={textCase}\n            interaction={interaction}\n            animation={animation}\n            textStyle={textStyle}\n            onTagClick={onTagClick}\n            draggable={draggable}\n            onSortEnd={onSortEnd}\n            onRemoveTag={removeTag}\n            direction={direction}\n            inlineTags={inlineTags}\n            activeTagIndex={activeTagIndex}\n            setActiveTagIndex={setActiveTagIndex}\n            classStyleProps={{\n              tagListClasses: styleClasses?.tagList,\n              tagClasses: styleClasses?.tag,\n            }}\n            disabled={disabled}\n          />\n        ) : (\n          !enableAutocomplete && (\n            <div className=\"w-full\">\n              <div\n                className={cn(\n                  `flex flex-row flex-wrap items-center gap-2 p-2 w-full rounded-md border border-input bg-background text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50`,\n                  styleClasses?.inlineTagsContainer,\n                )}\n              >\n                <TagList\n                  tags={truncatedTags}\n                  customTagRenderer={customTagRenderer}\n                  variant={variant}\n                  size={size}\n                  shape={shape}\n                  borderStyle={borderStyle}\n                  textCase={textCase}\n                  interaction={interaction}\n                  animation={animation}\n                  textStyle={textStyle}\n                  onTagClick={onTagClick}\n                  draggable={draggable}\n                  onSortEnd={onSortEnd}\n                  onRemoveTag={removeTag}\n                  direction={direction}\n                  inlineTags={inlineTags}\n                  activeTagIndex={activeTagIndex}\n                  setActiveTagIndex={setActiveTagIndex}\n                  classStyleProps={{\n                    tagListClasses: styleClasses?.tagList,\n                    tagClasses: styleClasses?.tag,\n                  }}\n                  disabled={disabled}\n                />\n                <Input\n                  ref={inputRef}\n                  id={id}\n                  type=\"text\"\n                  placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                  value={inputValue}\n                  onChange={handleInputChange}\n                  onKeyDown={handleKeyDown}\n                  onFocus={handleInputFocus}\n                  onBlur={handleInputBlur}\n                  {...inputProps}\n                  className={cn(\n                    'border-0 h-5 bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 flex-1 w-fit',\n                    // className,\n                    styleClasses?.input,\n                  )}\n                  autoComplete={enableAutocomplete ? 'on' : 'off'}\n                  list={enableAutocomplete ? 'autocomplete-options' : undefined}\n                  disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                />\n              </div>\n            </div>\n          )\n        ))}\n      {enableAutocomplete ? (\n        <div className=\"w-full\">\n          <Autocomplete\n            tags={tags}\n            setTags={setTags}\n            setInputValue={setInputValue}\n            autocompleteOptions={filteredAutocompleteOptions as Tag[]}\n            setTagCount={setTagCount}\n            maxTags={maxTags}\n            onTagAdd={onTagAdd}\n            onTagRemove={onTagRemove}\n            allowDuplicates={allowDuplicates ?? false}\n            inlineTags={inlineTags}\n            usePortal={usePortal}\n            classStyleProps={{\n              command: styleClasses?.autoComplete?.command,\n              popoverTrigger: styleClasses?.autoComplete?.popoverTrigger,\n              popoverContent: styleClasses?.autoComplete?.popoverContent,\n              commandList: styleClasses?.autoComplete?.commandList,\n              commandGroup: styleClasses?.autoComplete?.commandGroup,\n              commandItem: styleClasses?.autoComplete?.commandItem,\n            }}\n          >\n            {!usePopoverForTags ? (\n              !inlineTags ? (\n                // <CommandInput\n                //   placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                //   ref={inputRef}\n                //   value={inputValue}\n                //   disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                //   onChangeCapture={handleInputChange}\n                //   onKeyDown={handleKeyDown}\n                //   onFocus={handleInputFocus}\n                //   onBlur={handleInputBlur}\n                //   className={cn(\n                //     'w-full',\n                //     // className,\n                //     styleClasses?.input,\n                //   )}\n                // />\n                <Input\n                  ref={inputRef}\n                  id={id}\n                  type=\"text\"\n                  placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                  value={inputValue}\n                  onChange={handleInputChange}\n                  onKeyDown={handleKeyDown}\n                  onFocus={handleInputFocus}\n                  onBlur={handleInputBlur}\n                  {...inputProps}\n                  className={cn(\n                    'border-0 h-5 bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 flex-1 w-fit',\n                    // className,\n                    styleClasses?.input,\n                  )}\n                  autoComplete={enableAutocomplete ? 'on' : 'off'}\n                  list={enableAutocomplete ? 'autocomplete-options' : undefined}\n                  disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                />\n              ) : (\n                <div\n                  className={cn(\n                    `flex flex-row flex-wrap items-center p-2 gap-2 h-fit w-full bg-background text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50`,\n                    styleClasses?.inlineTagsContainer,\n                  )}\n                >\n                  <TagList\n                    tags={truncatedTags}\n                    customTagRenderer={customTagRenderer}\n                    variant={variant}\n                    size={size}\n                    shape={shape}\n                    borderStyle={borderStyle}\n                    textCase={textCase}\n                    interaction={interaction}\n                    animation={animation}\n                    textStyle={textStyle}\n                    onTagClick={onTagClick}\n                    draggable={draggable}\n                    onSortEnd={onSortEnd}\n                    onRemoveTag={removeTag}\n                    direction={direction}\n                    inlineTags={inlineTags}\n                    activeTagIndex={activeTagIndex}\n                    setActiveTagIndex={setActiveTagIndex}\n                    classStyleProps={{\n                      tagListClasses: styleClasses?.tagList,\n                      tagClasses: styleClasses?.tag,\n                    }}\n                    disabled={disabled}\n                  />\n                  {/* <CommandInput\n                    placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                    ref={inputRef}\n                    value={inputValue}\n                    disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                    onChangeCapture={handleInputChange}\n                    onKeyDown={handleKeyDown}\n                    onFocus={handleInputFocus}\n                    onBlur={handleInputBlur}\n                    inlineTags={inlineTags}\n                    className={cn(\n                      'border-0 flex-1 w-fit h-5',\n                      // className,\n                      styleClasses?.input,\n                    )}\n                  /> */}\n                  <Input\n                    ref={inputRef}\n                    id={id}\n                    type=\"text\"\n                    placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                    value={inputValue}\n                    onChange={handleInputChange}\n                    onKeyDown={handleKeyDown}\n                    onFocus={handleInputFocus}\n                    onBlur={handleInputBlur}\n                    {...inputProps}\n                    className={cn(\n                      'border-0 h-5 bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 flex-1 w-fit',\n                      // className,\n                      styleClasses?.input,\n                    )}\n                    autoComplete={enableAutocomplete ? 'on' : 'off'}\n                    list={enableAutocomplete ? 'autocomplete-options' : undefined}\n                    disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                  />\n                </div>\n              )\n            ) : (\n              <TagPopover\n                tags={truncatedTags}\n                customTagRenderer={customTagRenderer}\n                variant={variant}\n                size={size}\n                shape={shape}\n                borderStyle={borderStyle}\n                textCase={textCase}\n                interaction={interaction}\n                animation={animation}\n                textStyle={textStyle}\n                onTagClick={onTagClick}\n                draggable={draggable}\n                onSortEnd={onSortEnd}\n                onRemoveTag={removeTag}\n                direction={direction}\n                activeTagIndex={activeTagIndex}\n                setActiveTagIndex={setActiveTagIndex}\n                classStyleProps={{\n                  popoverClasses: styleClasses?.tagPopover,\n                  tagListClasses: styleClasses?.tagList,\n                  tagClasses: styleClasses?.tag,\n                }}\n                disabled={disabled}\n              >\n                {/* <CommandInput\n                  placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                  ref={inputRef}\n                  value={inputValue}\n                  disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                  onChangeCapture={handleInputChange}\n                  onKeyDown={handleKeyDown}\n                  onFocus={handleInputFocus}\n                  onBlur={handleInputBlur}\n                  className={cn(\n                    'w-full',\n                    // className,\n                    styleClasses?.input,\n                  )}\n                /> */}\n                <Input\n                  ref={inputRef}\n                  id={id}\n                  type=\"text\"\n                  placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                  value={inputValue}\n                  onChange={handleInputChange}\n                  onKeyDown={handleKeyDown}\n                  onFocus={handleInputFocus}\n                  onBlur={handleInputBlur}\n                  {...inputProps}\n                  className={cn(\n                    'border-0 h-5 bg-transparent focus-visible:ring-0 focus-visible:ring-transparent focus-visible:ring-offset-0 flex-1 w-fit',\n                    // className,\n                    styleClasses?.input,\n                  )}\n                  autoComplete={enableAutocomplete ? 'on' : 'off'}\n                  list={enableAutocomplete ? 'autocomplete-options' : undefined}\n                  disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                />\n              </TagPopover>\n            )}\n          </Autocomplete>\n        </div>\n      ) : (\n        <div className=\"w-full\">\n          {!usePopoverForTags ? (\n            !inlineTags ? (\n              <Input\n                ref={inputRef}\n                id={id}\n                type=\"text\"\n                placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                value={inputValue}\n                onChange={handleInputChange}\n                onKeyDown={handleKeyDown}\n                onFocus={handleInputFocus}\n                onBlur={handleInputBlur}\n                {...inputProps}\n                className={cn(\n                  styleClasses?.input,\n                  // className\n                )}\n                autoComplete={enableAutocomplete ? 'on' : 'off'}\n                list={enableAutocomplete ? 'autocomplete-options' : undefined}\n                disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n              />\n            ) : null\n          ) : (\n            <TagPopover\n              tags={truncatedTags}\n              customTagRenderer={customTagRenderer}\n              variant={variant}\n              size={size}\n              shape={shape}\n              borderStyle={borderStyle}\n              textCase={textCase}\n              interaction={interaction}\n              animation={animation}\n              textStyle={textStyle}\n              onTagClick={onTagClick}\n              draggable={draggable}\n              onSortEnd={onSortEnd}\n              onRemoveTag={removeTag}\n              direction={direction}\n              activeTagIndex={activeTagIndex}\n              setActiveTagIndex={setActiveTagIndex}\n              classStyleProps={{\n                popoverClasses: styleClasses?.tagPopover,\n                tagListClasses: styleClasses?.tagList,\n                tagClasses: styleClasses?.tag,\n              }}\n              disabled={disabled}\n            >\n              <Input\n                ref={inputRef}\n                id={id}\n                type=\"text\"\n                placeholder={maxTags !== undefined && tags.length >= maxTags ? placeholderWhenFull : placeholder}\n                value={inputValue}\n                onChange={handleInputChange}\n                onKeyDown={handleKeyDown}\n                onFocus={handleInputFocus}\n                onBlur={handleInputBlur}\n                {...inputProps}\n                autoComplete={enableAutocomplete ? 'on' : 'off'}\n                list={enableAutocomplete ? 'autocomplete-options' : undefined}\n                disabled={disabled || (maxTags !== undefined && tags.length >= maxTags)}\n                className={cn(\n                  'border-0 w-full',\n                  styleClasses?.input,\n                  // className\n                )}\n              />\n            </TagPopover>\n          )}\n        </div>\n      )}\n\n      {showCount && maxTags && (\n        <div className=\"flex\">\n          <span className=\"text-muted-foreground text-sm mt-1 ml-auto\">\n            {`${tagCount}`}/{`${maxTags}`}\n          </span>\n        </div>\n      )}\n      {clearAll && (\n        <Button type=\"button\" onClick={handleClearAll} className={cn('mt-2', styleClasses?.clearAllButton)}>\n          Clear All\n        </Button>\n      )}\n    </div>\n  );\n});\n\nTagInput.displayName = 'TagInput';\n\nexport { TagInput };\n",
      "type": "registry:component"
    },
    {
      "path": "registry/default/components/tag-list.tsx",
      "content": "import React from 'react';\nimport { TagInputStyleClassesProps, type Tag as TagType } from '@/registry/default/components/tag-input';\nimport { Tag, TagProps } from '@/registry/default/components/tag';\nimport SortableList, { SortableItem } from 'react-easy-sort';\nimport { cn } from '@/registry/default/lib/utils';\n\nexport type TagListProps = {\n  tags: TagType[];\n  customTagRenderer?: (tag: TagType, isActiveTag: boolean) => React.ReactNode;\n  direction?: TagProps['direction'];\n  onSortEnd: (oldIndex: number, newIndex: number) => void;\n  className?: string;\n  inlineTags?: boolean;\n  activeTagIndex?: number | null;\n  setActiveTagIndex?: (index: number | null) => void;\n  classStyleProps: {\n    tagListClasses: TagInputStyleClassesProps['tagList'];\n    tagClasses: TagInputStyleClassesProps['tag'];\n  };\n  disabled?: boolean;\n} & Omit<TagProps, 'tagObj'>;\n\nconst DropTarget: React.FC = () => {\n  return <div className={cn('h-full rounded-md bg-secondary/50')} />;\n};\n\nexport const TagList: React.FC<TagListProps> = ({\n  tags,\n  customTagRenderer,\n  direction,\n  draggable,\n  onSortEnd,\n  className,\n  inlineTags,\n  activeTagIndex,\n  setActiveTagIndex,\n  classStyleProps,\n  disabled,\n  ...tagListProps\n}) => {\n  const [draggedTagId, setDraggedTagId] = React.useState<string | null>(null);\n\n  const handleMouseDown = (id: string) => {\n    setDraggedTagId(id);\n  };\n\n  const handleMouseUp = () => {\n    setDraggedTagId(null);\n  };\n\n  return (\n    <>\n      {!inlineTags ? (\n        <div\n          className={cn(\n            'rounded-md w-full',\n            // className,\n            {\n              'flex flex-wrap gap-2': direction === 'row',\n              'flex flex-col gap-2': direction === 'column',\n            },\n            classStyleProps?.tagListClasses?.container,\n          )}\n        >\n          {draggable ? (\n            <SortableList\n              onSortEnd={onSortEnd}\n              // className=\"flex flex-wrap gap-2 list\"\n              className={`flex flex-wrap gap-2 list ${classStyleProps?.tagListClasses?.sortableList}`}\n              dropTarget={<DropTarget />}\n            >\n              {tags.map((tagObj, index) => (\n                <SortableItem key={tagObj.id}>\n                  <div\n                    onMouseDown={() => handleMouseDown(tagObj.id)}\n                    onMouseLeave={handleMouseUp}\n                    className={cn(\n                      {\n                        'border border-solid border-primary rounded-md': draggedTagId === tagObj.id,\n                      },\n                      'transition-all duration-200 ease-in-out',\n                    )}\n                  >\n                    {customTagRenderer ? (\n                      customTagRenderer(tagObj, index === activeTagIndex)\n                    ) : (\n                      <Tag\n                        tagObj={tagObj}\n                        isActiveTag={index === activeTagIndex}\n                        direction={direction}\n                        draggable={draggable}\n                        tagClasses={classStyleProps?.tagClasses}\n                        {...tagListProps}\n                        disabled={disabled}\n                      />\n                    )}\n                  </div>\n                </SortableItem>\n              ))}\n            </SortableList>\n          ) : (\n            tags.map((tagObj, index) =>\n              customTagRenderer ? (\n                customTagRenderer(tagObj, index === activeTagIndex)\n              ) : (\n                <Tag\n                  key={tagObj.id}\n                  tagObj={tagObj}\n                  isActiveTag={index === activeTagIndex}\n                  direction={direction}\n                  draggable={draggable}\n                  tagClasses={classStyleProps?.tagClasses}\n                  {...tagListProps}\n                  disabled={disabled}\n                />\n              ),\n            )\n          )}\n        </div>\n      ) : (\n        <>\n          {draggable ? (\n            <SortableList onSortEnd={onSortEnd} className=\"flex flex-wrap gap-2 list\" dropTarget={<DropTarget />}>\n              {tags.map((tagObj, index) => (\n                <SortableItem key={tagObj.id}>\n                  <div\n                    onMouseDown={() => handleMouseDown(tagObj.id)}\n                    onMouseLeave={handleMouseUp}\n                    className={cn(\n                      {\n                        'border border-solid border-primary rounded-md': draggedTagId === tagObj.id,\n                      },\n                      'transition-all duration-200 ease-in-out',\n                    )}\n                  >\n                    {customTagRenderer ? (\n                      customTagRenderer(tagObj, index === activeTagIndex)\n                    ) : (\n                      <Tag\n                        tagObj={tagObj}\n                        isActiveTag={index === activeTagIndex}\n                        direction={direction}\n                        draggable={draggable}\n                        tagClasses={classStyleProps?.tagClasses}\n                        {...tagListProps}\n                        disabled={disabled}\n                      />\n                    )}\n                  </div>\n                </SortableItem>\n              ))}\n            </SortableList>\n          ) : (\n            tags.map((tagObj, index) =>\n              customTagRenderer ? (\n                customTagRenderer(tagObj, index === activeTagIndex)\n              ) : (\n                <Tag\n                  key={tagObj.id}\n                  tagObj={tagObj}\n                  isActiveTag={index === activeTagIndex}\n                  direction={direction}\n                  draggable={draggable}\n                  tagClasses={classStyleProps?.tagClasses}\n                  {...tagListProps}\n                  disabled={disabled}\n                />\n              ),\n            )\n          )}\n        </>\n      )}\n    </>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "registry/default/components/tag-popover.tsx",
      "content": "import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { TagInputStyleClassesProps, type Tag as TagType } from '@/registry/default/components/tag-input';\nimport { TagList, TagListProps } from '@/registry/default/components/tag-list';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/registry/default/lib/utils';\n\ntype TagPopoverProps = {\n  children: React.ReactNode;\n  tags: TagType[];\n  customTagRenderer?: (tag: TagType, isActiveTag: boolean) => React.ReactNode;\n  activeTagIndex?: number | null;\n  setActiveTagIndex?: (index: number | null) => void;\n  classStyleProps: {\n    popoverClasses: TagInputStyleClassesProps['tagPopover'];\n    tagListClasses: TagInputStyleClassesProps['tagList'];\n    tagClasses: TagInputStyleClassesProps['tag'];\n  };\n  disabled?: boolean;\n  usePortal?: boolean;\n} & TagListProps;\n\nexport const TagPopover: React.FC<TagPopoverProps> = ({\n  children,\n  tags,\n  customTagRenderer,\n  activeTagIndex,\n  setActiveTagIndex,\n  classStyleProps,\n  disabled,\n  usePortal,\n  ...tagProps\n}) => {\n  const triggerContainerRef = useRef<HTMLDivElement | null>(null);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const popoverContentRef = useRef<HTMLDivElement | null>(null);\n  const inputRef = useRef<HTMLInputElement | null>(null);\n\n  const [popoverWidth, setPopoverWidth] = useState<number>(0);\n  const [isPopoverOpen, setIsPopoverOpen] = useState(false);\n  const [inputFocused, setInputFocused] = useState(false);\n  const [sideOffset, setSideOffset] = useState<number>(0);\n\n  useEffect(() => {\n    const handleResize = () => {\n      if (triggerContainerRef.current && triggerRef.current) {\n        setPopoverWidth(triggerContainerRef.current.offsetWidth);\n        setSideOffset(triggerContainerRef.current.offsetWidth - triggerRef?.current?.offsetWidth);\n      }\n    };\n\n    handleResize(); // Call on mount and layout changes\n\n    window.addEventListener('resize', handleResize); // Adjust on window resize\n    return () => window.removeEventListener('resize', handleResize);\n  }, [triggerContainerRef, triggerRef]);\n\n  // Close the popover when clicking outside of it\n  useEffect(() => {\n    const handleOutsideClick = (event: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent) => {\n      if (\n        isPopoverOpen &&\n        triggerContainerRef.current &&\n        popoverContentRef.current &&\n        !triggerContainerRef.current.contains(event.target as Node) &&\n        !popoverContentRef.current.contains(event.target as Node)\n      ) {\n        setIsPopoverOpen(false);\n      }\n    };\n\n    document.addEventListener('mousedown', handleOutsideClick);\n\n    return () => {\n      document.removeEventListener('mousedown', handleOutsideClick);\n    };\n  }, [isPopoverOpen]);\n\n  const handleOpenChange = useCallback(\n    (open: boolean) => {\n      if (open && triggerContainerRef.current) {\n        setPopoverWidth(triggerContainerRef.current.offsetWidth);\n      }\n\n      if (open) {\n        inputRef.current?.focus();\n        setIsPopoverOpen(open);\n      }\n    },\n    [inputFocused],\n  );\n\n  const handleInputFocus = (event: React.FocusEvent<HTMLInputElement> | React.FocusEvent<HTMLTextAreaElement>) => {\n    // Only set inputFocused to true if the popover is already open.\n    // This will prevent the popover from opening due to an input focus if it was initially closed.\n    if (isPopoverOpen) {\n      setInputFocused(true);\n    }\n\n    const userOnFocus = (children as React.ReactElement<any>).props.onFocus;\n    if (userOnFocus) userOnFocus(event);\n  };\n\n  const handleInputBlur = (event: React.FocusEvent<HTMLInputElement> | React.FocusEvent<HTMLTextAreaElement>) => {\n    setInputFocused(false);\n\n    // Allow the popover to close if no other interactions keep it open\n    if (!isPopoverOpen) {\n      setIsPopoverOpen(false);\n    }\n\n    const userOnBlur = (children as React.ReactElement<any>).props.onBlur;\n    if (userOnBlur) userOnBlur(event);\n  };\n\n  return (\n    <Popover open={isPopoverOpen} onOpenChange={handleOpenChange} modal={usePortal}>\n      <div\n        className=\"relative flex items-center rounded-md border border-input bg-transparent pr-3\"\n        ref={triggerContainerRef}\n      >\n        {React.cloneElement(children as React.ReactElement<any>, {\n          onFocus: handleInputFocus,\n          onBlur: handleInputBlur,\n          ref: inputRef,\n        })}\n        <PopoverTrigger asChild>\n          <Button\n            ref={triggerRef}\n            variant=\"ghost\"\n            size=\"icon\"\n            role=\"combobox\"\n            className={cn(`hover:bg-transparent`, classStyleProps?.popoverClasses?.popoverTrigger)}\n            onClick={() => setIsPopoverOpen(!isPopoverOpen)}\n          >\n            <svg\n              xmlns=\"http://www.w3.org/2000/svg\"\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              className={`lucide lucide-chevron-down h-4 w-4 shrink-0 opacity-50 ${isPopoverOpen ? 'rotate-180' : 'rotate-0'}`}\n            >\n              <path d=\"m6 9 6 6 6-6\"></path>\n            </svg>\n          </Button>\n        </PopoverTrigger>\n      </div>\n      <PopoverContent\n        ref={popoverContentRef}\n        className={cn(`w-full space-y-3`, classStyleProps?.popoverClasses?.popoverContent)}\n        style={{\n          marginLeft: `-${sideOffset}px`,\n          width: `${popoverWidth}px`,\n        }}\n      >\n        <div className=\"space-y-1\">\n          <h4 className=\"text-sm font-medium leading-none\">Entered Tags</h4>\n          <p className=\"text-sm text-muted-foregrounsd text-left\">These are the tags you&apos;ve entered.</p>\n        </div>\n        <TagList\n          tags={tags}\n          customTagRenderer={customTagRenderer}\n          activeTagIndex={activeTagIndex}\n          setActiveTagIndex={setActiveTagIndex}\n          classStyleProps={{\n            tagListClasses: classStyleProps?.tagListClasses,\n            tagClasses: classStyleProps?.tagClasses,\n          }}\n          {...tagProps}\n          disabled={disabled}\n        />\n      </PopoverContent>\n    </Popover>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "registry/default/components/tag-autocomplete.tsx",
      "content": "import React, { useCallback, useEffect, useRef, useState } from 'react';\n// import { Command, CommandList, CommandItem, CommandGroup, CommandEmpty } from '../ui/command';\nimport { TagInputStyleClassesProps, type Tag as TagType } from '@/registry/default/components/tag-input';\nimport { cn } from '@/registry/default/lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { Button } from '@/components/ui/button';\n\ntype AutocompleteProps = {\n  tags: TagType[];\n  setTags: React.Dispatch<React.SetStateAction<TagType[]>>;\n  setInputValue: React.Dispatch<React.SetStateAction<string>>;\n  setTagCount: React.Dispatch<React.SetStateAction<number>>;\n  autocompleteOptions: TagType[];\n  maxTags?: number;\n  onTagAdd?: (tag: string) => void;\n  onTagRemove?: (tag: string) => void;\n  allowDuplicates: boolean;\n  children: React.ReactNode;\n  inlineTags?: boolean;\n  classStyleProps: TagInputStyleClassesProps['autoComplete'];\n  usePortal?: boolean;\n};\n\nexport const Autocomplete: React.FC<AutocompleteProps> = ({\n  tags,\n  setTags,\n  setInputValue,\n  setTagCount,\n  autocompleteOptions,\n  maxTags,\n  onTagAdd,\n  onTagRemove,\n  allowDuplicates,\n  inlineTags,\n  children,\n  classStyleProps,\n  usePortal,\n}) => {\n  const triggerContainerRef = useRef<HTMLDivElement | null>(null);\n  const triggerRef = useRef<HTMLButtonElement | null>(null);\n  const inputRef = useRef<HTMLInputElement | null>(null);\n  const popoverContentRef = useRef<HTMLDivElement | null>(null);\n\n  const [popoverWidth, setPopoverWidth] = useState<number>(0);\n  const [isPopoverOpen, setIsPopoverOpen] = useState(false);\n  const [inputFocused, setInputFocused] = useState(false);\n  const [popooverContentTop, setPopoverContentTop] = useState<number>(0);\n  const [selectedIndex, setSelectedIndex] = useState<number>(-1);\n\n  // Dynamically calculate the top position for the popover content\n  useEffect(() => {\n    if (!triggerContainerRef.current || !triggerRef.current) return;\n    setPopoverContentTop(\n      triggerContainerRef.current?.getBoundingClientRect().bottom - triggerRef.current?.getBoundingClientRect().bottom,\n    );\n  }, [tags]);\n\n  // Close the popover when clicking outside of it\n  useEffect(() => {\n    const handleOutsideClick = (event: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent) => {\n      if (\n        isPopoverOpen &&\n        triggerContainerRef.current &&\n        popoverContentRef.current &&\n        !triggerContainerRef.current.contains(event.target as Node) &&\n        !popoverContentRef.current.contains(event.target as Node)\n      ) {\n        setIsPopoverOpen(false);\n      }\n    };\n\n    document.addEventListener('mousedown', handleOutsideClick);\n\n    return () => {\n      document.removeEventListener('mousedown', handleOutsideClick);\n    };\n  }, [isPopoverOpen]);\n\n  const handleOpenChange = useCallback(\n    (open: boolean) => {\n      if (open && triggerContainerRef.current) {\n        const { width } = triggerContainerRef.current.getBoundingClientRect();\n        setPopoverWidth(width);\n      }\n\n      if (open) {\n        inputRef.current?.focus();\n        setIsPopoverOpen(open);\n      }\n    },\n    [inputFocused],\n  );\n\n  const handleInputFocus = (event: React.FocusEvent<HTMLInputElement> | React.FocusEvent<HTMLTextAreaElement>) => {\n    if (triggerContainerRef.current) {\n      const { width } = triggerContainerRef.current.getBoundingClientRect();\n      setPopoverWidth(width);\n      setIsPopoverOpen(true);\n    }\n\n    // Only set inputFocused to true if the popover is already open.\n    // This will prevent the popover from opening due to an input focus if it was initially closed.\n    if (isPopoverOpen) {\n      setInputFocused(true);\n    }\n\n    const userOnFocus = (children as React.ReactElement<any>).props.onFocus;\n    if (userOnFocus) userOnFocus(event);\n  };\n\n  const handleInputBlur = (event: React.FocusEvent<HTMLInputElement> | React.FocusEvent<HTMLTextAreaElement>) => {\n    setInputFocused(false);\n\n    // Allow the popover to close if no other interactions keep it open\n    if (!isPopoverOpen) {\n      setIsPopoverOpen(false);\n    }\n\n    const userOnBlur = (children as React.ReactElement<any>).props.onBlur;\n    if (userOnBlur) userOnBlur(event);\n  };\n\n  const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n    if (!isPopoverOpen) return;\n\n    switch (event.key) {\n      case 'ArrowUp':\n        event.preventDefault();\n        setSelectedIndex((prevIndex) => (prevIndex <= 0 ? autocompleteOptions.length - 1 : prevIndex - 1));\n        break;\n      case 'ArrowDown':\n        event.preventDefault();\n        setSelectedIndex((prevIndex) => (prevIndex === autocompleteOptions.length - 1 ? 0 : prevIndex + 1));\n        break;\n      case 'Enter':\n        event.preventDefault();\n        if (selectedIndex !== -1) {\n          toggleTag(autocompleteOptions[selectedIndex]);\n          setSelectedIndex(-1);\n        }\n        break;\n    }\n  };\n\n  const toggleTag = (option: TagType) => {\n    // Check if the tag already exists in the array\n    const index = tags.findIndex((tag) => tag.text === option.text);\n\n    if (index >= 0) {\n      // Tag exists, remove it\n      const newTags = tags.filter((_, i) => i !== index);\n      setTags(newTags);\n      setTagCount((prevCount) => prevCount - 1);\n      if (onTagRemove) {\n        onTagRemove(option.text);\n      }\n    } else {\n      // Tag doesn't exist, add it if allowed\n      if (!allowDuplicates && tags.some((tag) => tag.text === option.text)) {\n        // If duplicates aren't allowed and a tag with the same text exists, do nothing\n        return;\n      }\n\n      // Add the tag if it doesn't exceed max tags, if applicable\n      if (!maxTags || tags.length < maxTags) {\n        setTags([...tags, option]);\n        setTagCount((prevCount) => prevCount + 1);\n        setInputValue('');\n        if (onTagAdd) {\n          onTagAdd(option.text);\n        }\n      }\n    }\n    setSelectedIndex(-1);\n  };\n\n  const childrenWithProps = React.cloneElement(children as React.ReactElement<any>, {\n    onKeyDown: handleKeyDown,\n    onFocus: handleInputFocus,\n    onBlur: handleInputBlur,\n    ref: inputRef,\n  });\n\n  return (\n    <div\n      className={cn(\n        'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',\n        classStyleProps?.command,\n      )}\n    >\n      <Popover open={isPopoverOpen} onOpenChange={handleOpenChange} modal={usePortal}>\n        <div\n          className=\"relative h-full flex items-center rounded-md border bg-transparent pr-3\"\n          ref={triggerContainerRef}\n        >\n          {childrenWithProps}\n          <PopoverTrigger asChild ref={triggerRef}>\n            <Button\n              variant=\"ghost\"\n              size=\"icon\"\n              role=\"combobox\"\n              className={cn(`hover:bg-transparent ${!inlineTags ? 'ml-auto' : ''}`, classStyleProps?.popoverTrigger)}\n              onClick={() => {\n                setIsPopoverOpen(!isPopoverOpen);\n              }}\n            >\n              <svg\n                xmlns=\"http://www.w3.org/2000/svg\"\n                width=\"24\"\n                height=\"24\"\n                viewBox=\"0 0 24 24\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                strokeWidth=\"2\"\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                className={`lucide lucide-chevron-down h-4 w-4 shrink-0 opacity-50 ${isPopoverOpen ? 'rotate-180' : 'rotate-0'}`}\n              >\n                <path d=\"m6 9 6 6 6-6\"></path>\n              </svg>\n            </Button>\n          </PopoverTrigger>\n        </div>\n        <PopoverContent\n          ref={popoverContentRef}\n          side=\"bottom\"\n          align=\"start\"\n          forceMount\n          className={cn(`p-0 relative`, classStyleProps?.popoverContent)}\n          style={{\n            top: `${popooverContentTop}px`,\n            marginLeft: `calc(-${popoverWidth}px + 36px)`,\n            width: `${popoverWidth}px`,\n            minWidth: `${popoverWidth}px`,\n            zIndex: 9999,\n          }}\n        >\n          <div\n            className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', classStyleProps?.commandList)}\n            style={{\n              minHeight: '68px',\n            }}\n            key={autocompleteOptions.length}\n          >\n            {autocompleteOptions.length > 0 ? (\n              <div\n                key={autocompleteOptions.length}\n                role=\"group\"\n                className={cn('overflow-y-auto overflow-hidden p-1 text-foreground', classStyleProps?.commandGroup)}\n                style={{\n                  minHeight: '68px',\n                }}\n              >\n                <span className=\"text-muted-foreground font-medium text-sm py-1.5 px-2 pb-2\">Suggestions</span>\n                <div role=\"separator\" className=\"py-0.5\" />\n                {autocompleteOptions.map((option, index) => {\n                  const isSelected = index === selectedIndex;\n                  return (\n                    <div\n                      key={option.id}\n                      role=\"option\"\n                      aria-selected={isSelected}\n                      className={cn(\n                        'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-accent',\n                        isSelected && 'bg-accent text-accent-foreground',\n                        classStyleProps?.commandItem,\n                      )}\n                      data-value={option.text}\n                      onClick={() => toggleTag(option)}\n                    >\n                      <div className=\"w-full flex items-center gap-2\">\n                        {option.text}\n                        {tags.some((tag) => tag.text === option.text) && (\n                          <svg\n                            xmlns=\"http://www.w3.org/2000/svg\"\n                            width=\"14\"\n                            height=\"14\"\n                            viewBox=\"0 0 24 24\"\n                            fill=\"none\"\n                            stroke=\"currentColor\"\n                            strokeWidth=\"2\"\n                            strokeLinecap=\"round\"\n                            strokeLinejoin=\"round\"\n                            className=\"lucide lucide-check\"\n                          >\n                            <path d=\"M20 6 9 17l-5-5\"></path>\n                          </svg>\n                        )}\n                      </div>\n                    </div>\n                  );\n                })}\n              </div>\n            ) : (\n              <div className=\"py-6 text-center text-sm\">No results found.</div>\n            )}\n          </div>\n        </PopoverContent>\n      </Popover>\n    </div>\n  );\n};\n",
      "type": "registry:component"
    }
  ]
}
