{"$schema":"https:\/\/ui.particle.academy\/schema\/registry-item.json","name":"pillbox","type":"registry:ui","title":"Pillbox","description":"Pillbox from react-fancy","package":"react-fancy","dependencies":["lucide-react"],"registryDependencies":[],"files":[{"path":"components\/fancy\/pillbox\/Pillbox.tsx","content":"import { forwardRef, useCallback, useRef, useState } from \"react\";\r\nimport { X } from \"lucide-react\";\r\nimport { cn } from \"..\/..\/utils\/cn\";\r\nimport { useControllableState } from \"..\/..\/hooks\/use-controllable-state\";\r\nimport type { PillboxProps } from \".\/Pillbox.types\";\r\n\r\nexport const Pillbox = forwardRef<HTMLDivElement, PillboxProps>(\r\n  function Pillbox(\r\n    {\r\n      value: controlledValue,\r\n      defaultValue = [],\r\n      onChange,\r\n      placeholder = \"Type and press Enter...\",\r\n      maxItems,\r\n      disabled = false,\r\n      className,\r\n    },\r\n    ref,\r\n  ) {\r\n    const [items, setItems] = useControllableState(\r\n      controlledValue,\r\n      defaultValue,\r\n      onChange,\r\n    );\r\n    const [input, setInput] = useState(\"\");\r\n    const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n    const addItem = useCallback(\r\n      (text: string) => {\r\n        const trimmed = text.trim();\r\n        if (!trimmed || items.includes(trimmed)) return;\r\n        if (maxItems && items.length >= maxItems) return;\r\n        setItems([...items, trimmed]);\r\n        setInput(\"\");\r\n      },\r\n      [items, setItems, maxItems],\r\n    );\r\n\r\n    const removeItem = useCallback(\r\n      (index: number) => {\r\n        setItems(items.filter((_, i) => i !== index));\r\n      },\r\n      [items, setItems],\r\n    );\r\n\r\n    const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\r\n      if (e.key === \"Enter\") {\r\n        e.preventDefault();\r\n        addItem(input);\r\n      } else if (e.key === \"Backspace\" && !input && items.length > 0) {\r\n        removeItem(items.length - 1);\r\n      }\r\n    };\r\n\r\n    return (\r\n      <div\r\n        data-react-fancy-pillbox=\"\"\r\n        ref={ref}\r\n        className={cn(\r\n          \"flex flex-wrap items-center gap-1.5 rounded-lg border border-zinc-200 bg-white px-3 py-2 transition-[border-color,box-shadow] duration-150 focus-within:border-blue-500 focus-within:ring-2 focus-within:ring-blue-500\/40 dark:border-zinc-700 dark:bg-[#1e1e24] dark:text-zinc-100 dark:focus-within:border-blue-400 dark:focus-within:ring-blue-400\/20\",\r\n          disabled && \"cursor-not-allowed opacity-50\",\r\n          className,\r\n        )}\r\n        onClick={() => inputRef.current?.focus()}\r\n      >\r\n        {items.map((item, i) => (\r\n          <span\r\n            key={`${item}-${i}`}\r\n            className=\"inline-flex items-center gap-1 rounded-md bg-zinc-100 px-2 py-0.5 text-sm dark:bg-zinc-800\"\r\n          >\r\n            {item}\r\n            {!disabled && (\r\n              <button\r\n                type=\"button\"\r\n                onClick={(e) => {\r\n                  e.stopPropagation();\r\n                  removeItem(i);\r\n                }}\r\n                className=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\r\n                aria-label={`Remove ${item}`}\r\n              >\r\n                <X size={12} \/>\r\n              <\/button>\r\n            )}\r\n          <\/span>\r\n        ))}\r\n        <input\r\n          ref={inputRef}\r\n          type=\"text\"\r\n          value={input}\r\n          onChange={(e) => setInput(e.target.value)}\r\n          onKeyDown={handleKeyDown}\r\n          placeholder={items.length === 0 ? placeholder : \"\"}\r\n          disabled={disabled}\r\n          className=\"min-w-[80px] flex-1 bg-transparent text-sm outline-none placeholder:text-zinc-400\"\r\n        \/>\r\n      <\/div>\r\n    );\r\n  },\r\n);\r\n\r\nPillbox.displayName = \"Pillbox\";\r\n","type":"registry:ui","target":"components\/fancy\/pillbox\/Pillbox.tsx"},{"path":"components\/fancy\/pillbox\/Pillbox.types.ts","content":"export interface PillboxProps {\r\n  value?: string[];\r\n  defaultValue?: string[];\r\n  onChange?: (values: string[]) => void;\r\n  placeholder?: string;\r\n  maxItems?: number;\r\n  disabled?: boolean;\r\n  className?: string;\r\n}\r\n","type":"registry:ui","target":"components\/fancy\/pillbox\/Pillbox.types.ts"},{"path":"components\/fancy\/pillbox\/index.ts","content":"export { Pillbox } from \".\/Pillbox\";\r\nexport type { PillboxProps } from \".\/Pillbox.types\";\r\n","type":"registry:ui","target":"components\/fancy\/pillbox\/index.ts"}]}