{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tailwind-taggroup",
  "type": "registry:ui",
  "title": "TagGroup",
  "dependencies": [
    "lucide-react",
    "react",
    "react-aria-components",
    "tailwind-merge",
    "tailwind-variants",
    "tailwindcss-react-aria-components",
    "tw-animate-css"
  ],
  "registryDependencies": [
    "https://react-aria.adobe.com/registry/tailwind-field.json",
    "https://react-aria.adobe.com/registry/tailwind-utils.json"
  ],
  "files": [
    {
      "path": "components/ui/TagGroup.tsx",
      "type": "registry:ui",
      "content": "'use client';\nimport {XIcon} from 'lucide-react';\nimport React, {createContext, useContext} from 'react';\nimport {\n  Tag as AriaTag,\n  TagGroup as AriaTagGroup,\n  type TagGroupProps as AriaTagGroupProps,\n  type TagProps as AriaTagProps,\n  Button,\n  TagList,\n  type TagListProps,\n  Text\n} from 'react-aria-components/TagGroup';\nimport {composeRenderProps} from 'react-aria-components/composeRenderProps';\nimport {twMerge} from 'tailwind-merge';\nimport {tv} from 'tailwind-variants';\nimport {Description, Label} from '@/registry/react-aria/ui/Field';\nimport {focusRing} from '@/registry/react-aria/lib/react-aria-utils';\n\nconst colors = {\n  gray: 'bg-white text-neutral-600 border-neutral-200 hover:border-neutral-300 dark:bg-neutral-900 dark:text-neutral-300 dark:border-neutral-600 dark:hover:border-neutral-500',\n  green:\n    'bg-green-100 text-green-700 border-green-200 hover:border-green-300 dark:bg-green-300/20 dark:text-green-400 dark:border-green-300/10 dark:hover:border-green-300/20',\n  yellow:\n    'bg-yellow-100 text-yellow-700 border-yellow-200 hover:border-yellow-300 dark:bg-yellow-300/20 dark:text-yellow-400 dark:border-yellow-300/10 dark:hover:border-yellow-300/20',\n  blue: 'bg-blue-100 text-blue-700 border-blue-200 hover:border-blue-300 dark:bg-blue-400/20 dark:text-blue-300 dark:border-blue-400/10 dark:hover:border-blue-400/20'\n};\n\ntype Color = keyof typeof colors;\nconst ColorContext = createContext<Color>('gray');\n\nconst tagStyles = tv({\n  extend: focusRing,\n  base: 'transition cursor-default text-xs rounded-full border px-3 py-0.5 flex items-center max-w-fit gap-1 font-sans [-webkit-tap-highlight-color:transparent]',\n  variants: {\n    color: {\n      gray: '',\n      green: '',\n      yellow: '',\n      blue: ''\n    },\n    allowsRemoving: {\n      true: 'pr-1'\n    },\n    isSelected: {\n      true: 'bg-blue-600 text-white border-transparent forced-colors:bg-[Highlight] forced-colors:text-[HighlightText] forced-color-adjust-none'\n    },\n    isDisabled: {\n      true: 'bg-neutral-100 dark:bg-transparent dark:border-white/20 text-neutral-300 dark:text-neutral-600 forced-colors:text-[GrayText]'\n    }\n  },\n  compoundVariants: (Object.keys(colors) as Color[]).map(color => ({\n    isSelected: false,\n    isDisabled: false,\n    color,\n    class: colors[color]\n  }))\n});\n\nexport interface TagGroupProps<T>\n  extends\n    Omit<AriaTagGroupProps, 'children'>,\n    Pick<TagListProps<T>, 'items' | 'children' | 'renderEmptyState'> {\n  color?: Color;\n  label?: string;\n  description?: string;\n  errorMessage?: string;\n}\n\nexport interface TagProps extends AriaTagProps {\n  color?: Color;\n}\n\nexport function TagGroup<T>({\n  label,\n  description,\n  errorMessage,\n  items,\n  children,\n  renderEmptyState,\n  ...props\n}: TagGroupProps<T>) {\n  return (\n    <AriaTagGroup {...props} className={twMerge('flex flex-col gap-2 font-sans', props.className)}>\n      <Label>{label}</Label>\n      <ColorContext.Provider value={props.color || 'gray'}>\n        <TagList items={items} renderEmptyState={renderEmptyState} className=\"flex flex-wrap gap-1\">\n          {children}\n        </TagList>\n      </ColorContext.Provider>\n      {description && <Description>{description}</Description>}\n      {errorMessage && (\n        <Text slot=\"errorMessage\" className=\"text-sm text-red-600\">\n          {errorMessage}\n        </Text>\n      )}\n    </AriaTagGroup>\n  );\n}\n\nconst removeButtonStyles = tv({\n  extend: focusRing,\n  base: 'cursor-default rounded-full transition-[background-color] p-0.5 flex items-center justify-center bg-transparent text-[inherit] border-0 hover:bg-black/10 dark:hover:bg-white/10 pressed:bg-black/20 dark:pressed:bg-white/20'\n});\n\nexport function Tag({children, color, ...props}: TagProps) {\n  let textValue = typeof children === 'string' ? children : undefined;\n  let groupColor = useContext(ColorContext);\n  return (\n    <AriaTag\n      textValue={textValue}\n      {...props}\n      className={composeRenderProps(props.className, (className, renderProps) =>\n        tagStyles({...renderProps, className, color: color || groupColor})\n      )}>\n      {composeRenderProps(children, (children, {allowsRemoving}) => (\n        <>\n          {children}\n          {allowsRemoving && (\n            <Button slot=\"remove\" className={removeButtonStyles}>\n              <XIcon aria-hidden className=\"w-3 h-3\" />\n            </Button>\n          )}\n        </>\n      ))}\n    </AriaTag>\n  );\n}\n"
    }
  ],
  "css": {
    "@plugin \"tailwindcss-react-aria-components\"": {},
    "@import \"tw-animate-css\"": {}
  }
}
