{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tags-input-components",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./registry/components/form/tags-input/index.tsx",
      "content": "'use client';\nimport { TagsInput } from '@/components/ui/tags-input';\nimport React, { useEffect, useRef, useState } from 'react';\n\nexport default function App() {\n  const [tags, setTags] = useState<string[]>([]);\n\n  return (\n    <div className='max-w-xl mx-auto py-16'>\n      <TagsInput tags={tags} setTags={setTags} className='lg:w-96' />\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "./components/ui/tags-input.tsx",
      "content": "'use client';\nimport { cn } from '@/lib/utils';\nimport type React from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\ninterface TagsInputProps {\n  tags: string[];\n  setTags: React.Dispatch<React.SetStateAction<string[]>>;\n  editTag?: boolean;\n  className?: string;\n}\n\nexport const TagsInput: React.FC<TagsInputProps> = ({\n  tags,\n  setTags,\n  editTag = true,\n  className,\n}) => {\n  const [input, setInput] = useState('');\n  const [editingIndex, setEditingIndex] = useState<number | null>(null);\n  const editInputRef = useRef<HTMLInputElement>(null);\n\n  const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {\n    const trimmedInput = input.trim();\n\n    if ((e.key === 'Enter' || e.key === ',') && trimmedInput) {\n      e.preventDefault();\n      if (editingIndex !== null) {\n        const updatedTags = [...tags];\n        updatedTags[editingIndex] = trimmedInput;\n        setTags(updatedTags);\n        setEditingIndex(null);\n      } else if (!tags.includes(trimmedInput)) {\n        setTags([...tags, trimmedInput]);\n      }\n      setInput('');\n    }\n  };\n\n  const handleRemoveTag = (tag: string) => {\n    setTags(tags.filter((t) => t !== tag));\n    if (editingIndex !== null) {\n      setEditingIndex(null);\n    }\n  };\n\n  const handleEditTag = (index: number) => {\n    if (editTag) {\n      setInput(tags[index]);\n      setEditingIndex(index);\n      setTimeout(() => editInputRef.current?.focus(), 0);\n    }\n  };\n\n  const handleBlur = () => {\n    if (editingIndex !== null) {\n      const updatedTags = [...tags];\n      const trimmedInput = input.trim();\n      if (trimmedInput) {\n        updatedTags[editingIndex] = trimmedInput;\n      } else {\n        updatedTags.splice(editingIndex, 1);\n      }\n      setTags(updatedTags);\n      setEditingIndex(null);\n    }\n    setInput('');\n  };\n\n  useEffect(() => {\n    if (editInputRef.current) {\n      editInputRef.current.style.width = `${input.length + 1}ch`;\n    }\n  }, [input]);\n\n  return (\n    <div\n      className={cn(\n        'flex flex-wrap w-full items-center gap-2 p-2 border-2 rounded-md focus-within:border-blue-500 dark:bg-neutral-950 bg-neutral-50',\n        className\n      )}\n    >\n      {tags.map((tag, index) => (\n        <div key={tag} className='relative'>\n          {editTag && editingIndex === index ? (\n            <input\n              ref={editInputRef}\n              type='text'\n              value={input}\n              onChange={(e) => setInput(e.target.value)}\n              onKeyDown={handleAddTag}\n              onBlur={handleBlur}\n              className='px-2 py-1 text-sm border dark:bg-neutral-800 bg-neutral-200 rounded-sm outline-hidden'\n              placeholder='Edit tag...'\n              style={{ width: `${input.length + 1 * 1.2}px` }}\n            />\n          ) : (\n            <div\n              onClick={() => handleEditTag(index)}\n              className='flex items-center gap-2 px-1 pl-2 py-1 text-sm font-medium text-white bg-blue-500 rounded-sm cursor-pointer hover:bg-blue-600'\n            >\n              {tag}\n              <button\n                onClick={(e) => {\n                  e.stopPropagation();\n                  handleRemoveTag(tag);\n                }}\n                className='text-primary px-1 focus:outline-hidden bg-primary-base rounded-sm'\n              >\n                &times;\n              </button>\n            </div>\n          )}\n        </div>\n      ))}\n      <input\n        type='text'\n        value={input}\n        onChange={(e) => setInput(e.target.value)}\n        onKeyDown={handleAddTag}\n        className={`grow px-2 py-1 text-sm border-none outline-hidden  dark:bg-neutral-800 bg-neutral-50 rounded-md ${\n          editingIndex !== null ? 'opacity-0' : 'opacity-100'\n        }`}\n        placeholder='Add a tag...'\n      />\n    </div>\n  );\n};\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}