{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chip",
  "title": "Chip",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/chip/chip.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { chipVariants, type ChipVariants } from './chip.variants'\n\nexport interface ChipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'onClose'>, ChipVariants {\n  closable?: boolean\n  onClose?: () => void\n}\n\nconst Chip = React.forwardRef<HTMLSpanElement, ChipProps>(\n  ({ className, variant, size, closable, onClose, children, ...props }, ref) => (\n    <span ref={ref} className={cn(chipVariants({ variant, size }), className)} {...props}>\n      {children}\n      {closable ? (\n        <button\n          type=\"button\"\n          aria-label={`Remove ${children ? '' : 'item'}`}\n          className=\"focus-visible:ring-ring hover:bg-foreground/10 ml-0.5 inline-flex min-h-6 min-w-6 items-center justify-center rounded-full focus-visible:ring-1 focus-visible:outline-none\"\n          onClick={(e) => {\n            e.stopPropagation()\n            onClose?.()\n          }}\n        >\n          <X className=\"size-3\" aria-hidden=\"true\" />\n        </button>\n      ) : null}\n    </span>\n  ),\n)\nChip.displayName = 'Chip'\n\nexport interface ChipGroupRenderProps {\n  selected: string[]\n  multiple: boolean\n  filter: boolean\n  isSelected: (value: string) => boolean\n  toggle: (value: string) => void\n}\n\nexport interface ChipGroupProps {\n  className?: string\n  selected?: string[]\n  multiple?: boolean\n  filter?: boolean\n  column?: boolean\n  mandatory?: boolean\n  max?: number\n  disabled?: boolean\n  onSelectedChange?: (value: string[]) => void\n  children?: (props: ChipGroupRenderProps) => React.ReactNode\n}\n\nconst ChipGroup = React.forwardRef<HTMLDivElement, ChipGroupProps>(\n  (\n    {\n      className,\n      selected = [],\n      multiple = false,\n      filter = false,\n      column = false,\n      mandatory = false,\n      max,\n      disabled = false,\n      onSelectedChange,\n      children,\n    },\n    ref,\n  ) => {\n    const isSelected = (value: string) => selected.includes(value)\n\n    const toggle = (value: string) => {\n      if (disabled) return\n\n      let newSelected: string[]\n\n      if (multiple) {\n        if (isSelected(value)) {\n          newSelected = selected.filter((v) => v !== value)\n        } else {\n          if (max && selected.length >= max) {\n            newSelected = [...selected.slice(1), value]\n          } else {\n            newSelected = [...selected, value]\n          }\n        }\n      } else {\n        if (isSelected(value) && !mandatory) {\n          newSelected = []\n        } else {\n          newSelected = [value]\n        }\n      }\n\n      onSelectedChange?.(newSelected)\n    }\n\n    return (\n      <div\n        ref={ref}\n        className={cn('flex flex-wrap gap-2', column && 'flex-col', filter && 'flex-wrap', className)}\n        data-chip-group=\"true\"\n        data-multiple={multiple || undefined}\n        data-filter={filter || undefined}\n      >\n        {children?.({ selected, multiple, filter, isSelected, toggle })}\n      </div>\n    )\n  },\n)\nChipGroup.displayName = 'ChipGroup'\n\nexport { Chip, ChipGroup }\n",
      "type": "registry:ui",
      "target": "~/components/ui/chip/chip.tsx"
    },
    {
      "path": "packages/registry-react/components/chip/chip.variants.ts",
      "content": "import type { VariantProps } from 'class-variance-authority'\nimport { cva } from 'class-variance-authority'\n\n/**\n * Variant definitions live in their own file (rather than the package\n * `index.ts`) so consuming Vue SFCs can import without creating a circular\n * dependency through the index. See card.variants.ts for the canonical\n * example + the SSR symptom that motivated the split.\n */\n\nexport const chipVariants = cva(\n  'inline-flex items-center justify-center gap-1 rounded-full text-xs font-medium w-fit whitespace-nowrap shrink-0 transition-colors duration-200 overflow-hidden focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n  {\n    variants: {\n      variant: {\n        default: 'bg-muted text-muted-foreground hover:bg-muted/80',\n        filled: 'bg-primary text-primary-foreground hover:bg-primary/90',\n        outlined: 'border border-current bg-transparent hover:bg-accent',\n        elevated: 'bg-primary/10 text-primary shadow-sm hover:bg-primary/20',\n        success: 'bg-[var(--success)]/10 text-[var(--success)] dark:text-[var(--success)] hover:bg-[var(--success)]/20',\n        warning: 'bg-[var(--warning)]/10 text-[var(--warning)] dark:text-[var(--warning)] hover:bg-[var(--warning)]/20',\n        destructive: 'bg-destructive/10 text-destructive dark:text-destructive hover:bg-destructive/20',\n      },\n      size: {\n        sm: 'h-6 px-2 text-xs',\n        default: 'h-7 px-2.5 text-xs',\n        lg: 'h-8 px-3 text-sm',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n)\n\nexport type ChipVariants = VariantProps<typeof chipVariants>\n",
      "type": "registry:ui",
      "target": "~/components/ui/chip/chip.variants.ts"
    },
    {
      "path": "packages/registry-react/components/chip/index.ts",
      "content": "export { Chip, ChipGroup, type ChipProps, type ChipGroupProps, type ChipGroupRenderProps } from './chip'\nexport { chipVariants, type ChipVariants } from './chip.variants'\n",
      "type": "registry:ui",
      "target": "~/components/ui/chip/index.ts"
    }
  ],
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Compact, removable tag — typically used inside `tags-input` or as a filter pill. Seven variants (`default`, `filled`, `outlined`, `elevated`, `success`, `warning`, `destructive`), three sizes, and an optional close button.",
  "categories": [
    "data-display"
  ]
}