{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "spinner",
  "title": "Spinner",
  "description": "Loading spinner with multiple animation variants - dots, bars, blocks, and brutal shadow spin",
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@boldkit/utils"
  ],
  "files": [
    {
      "path": "registry/default/ui/spinner.tsx",
      "content": "/* eslint-disable react-refresh/only-export-components */\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\nconst spinnerVariants = cva(\n  'inline-flex items-center justify-center',\n  {\n    variants: {\n      size: {\n        xs: 'h-3 w-3',\n        sm: 'h-4 w-4',\n        md: 'h-6 w-6',\n        lg: 'h-8 w-8',\n        xl: 'h-12 w-12',\n      },\n      variant: {\n        default: '',\n        dots: '',\n        bars: '',\n        blocks: '',\n        brutal: '',\n      },\n    },\n    defaultVariants: {\n      size: 'md',\n      variant: 'default',\n    },\n  }\n)\n\nexport interface SpinnerProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof spinnerVariants> {}\n\nconst Spinner = React.forwardRef<HTMLDivElement, SpinnerProps>(\n  ({ className, size, variant, ...props }, ref) => {\n    const sizeClasses = {\n      xs: { element: 'h-3 w-3', dot: 'h-1 w-1', bar: 'w-0.5 h-2', block: 'h-1 w-1', ring: 'h-3 w-3' },\n      sm: { element: 'h-4 w-4', dot: 'h-1 w-1', bar: 'w-0.5 h-2.5', block: 'h-1.5 w-1.5', ring: 'h-4 w-4' },\n      md: { element: 'h-6 w-6', dot: 'h-1.5 w-1.5', bar: 'w-1 h-4', block: 'h-2 w-2', ring: 'h-6 w-6' },\n      lg: { element: 'h-8 w-8', dot: 'h-2 w-2', bar: 'w-1 h-5', block: 'h-2.5 w-2.5', ring: 'h-8 w-8' },\n      xl: { element: 'h-12 w-12', dot: 'h-3 w-3', bar: 'w-1.5 h-8', block: 'h-4 w-4', ring: 'h-12 w-12' },\n    }\n\n    const currentSize = size ?? 'md'\n    const sizes = sizeClasses[currentSize]\n\n    if (variant === 'dots') {\n      return (\n        <div\n          ref={ref}\n          role=\"status\"\n          aria-label=\"Loading\"\n          className={cn(spinnerVariants({ size, variant }), 'gap-1', className)}\n          {...props}\n        >\n          <div className={cn(sizes.dot, 'bg-foreground animate-[brutal-dots_1.4s_ease-in-out_infinite]')} style={{ animationDelay: '0ms' }} />\n          <div className={cn(sizes.dot, 'bg-foreground animate-[brutal-dots_1.4s_ease-in-out_infinite]')} style={{ animationDelay: '200ms' }} />\n          <div className={cn(sizes.dot, 'bg-foreground animate-[brutal-dots_1.4s_ease-in-out_infinite]')} style={{ animationDelay: '400ms' }} />\n        </div>\n      )\n    }\n\n    if (variant === 'bars') {\n      return (\n        <div\n          ref={ref}\n          role=\"status\"\n          aria-label=\"Loading\"\n          className={cn(spinnerVariants({ size, variant }), 'gap-0.5', className)}\n          {...props}\n        >\n          <div className={cn(sizes.bar, 'bg-foreground animate-[brutal-bars_1.2s_ease-in-out_infinite]')} style={{ animationDelay: '0ms' }} />\n          <div className={cn(sizes.bar, 'bg-foreground animate-[brutal-bars_1.2s_ease-in-out_infinite]')} style={{ animationDelay: '150ms' }} />\n          <div className={cn(sizes.bar, 'bg-foreground animate-[brutal-bars_1.2s_ease-in-out_infinite]')} style={{ animationDelay: '300ms' }} />\n        </div>\n      )\n    }\n\n    if (variant === 'blocks') {\n      return (\n        <div\n          ref={ref}\n          role=\"status\"\n          aria-label=\"Loading\"\n          className={cn(spinnerVariants({ size, variant }), 'relative', className)}\n          {...props}\n        >\n          <div className=\"relative animate-[brutal-blocks_1.2s_linear_infinite]\">\n            <div className={cn(sizes.block, 'absolute bg-foreground')} style={{ top: 0, left: '50%', transform: 'translateX(-50%)' }} />\n            <div className={cn(sizes.block, 'absolute bg-foreground')} style={{ top: '50%', right: 0, transform: 'translateY(-50%)' }} />\n            <div className={cn(sizes.block, 'absolute bg-foreground')} style={{ bottom: 0, left: '50%', transform: 'translateX(-50%)' }} />\n            <div className={cn(sizes.block, 'absolute bg-foreground')} style={{ top: '50%', left: 0, transform: 'translateY(-50%)' }} />\n          </div>\n        </div>\n      )\n    }\n\n    if (variant === 'brutal') {\n      return (\n        <div\n          ref={ref}\n          role=\"status\"\n          aria-label=\"Loading\"\n          className={cn(spinnerVariants({ size, variant }), className)}\n          {...props}\n        >\n          <div className={cn(sizes.ring, 'relative')}>\n            <div className=\"absolute inset-0 bg-foreground border-3 border-foreground\" />\n            <div className=\"absolute inset-0 bg-foreground animate-[brutal-shadow-spin_1s_linear_infinite]\" style={{ boxShadow: '3px 3px 0px hsl(var(--primary))' }} />\n          </div>\n        </div>\n      )\n    }\n\n    // Default ring spinner\n    return (\n      <div\n        ref={ref}\n        role=\"status\"\n        aria-label=\"Loading\"\n        className={cn(spinnerVariants({ size, variant }), className)}\n        {...props}\n      >\n        <svg\n          className={cn(sizes.ring, 'animate-spin')}\n          xmlns=\"http://www.w3.org/2000/svg\"\n          fill=\"none\"\n          viewBox=\"0 0 24 24\"\n        >\n          <circle\n            className=\"opacity-25\"\n            cx=\"12\"\n            cy=\"12\"\n            r=\"10\"\n            stroke=\"currentColor\"\n            strokeWidth=\"4\"\n          />\n          <path\n            className=\"opacity-75\"\n            fill=\"currentColor\"\n            d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n          />\n        </svg>\n      </div>\n    )\n  }\n)\nSpinner.displayName = 'Spinner'\n\nexport { Spinner, spinnerVariants }\n",
      "type": "registry:ui",
      "target": "components/ui/spinner.tsx"
    }
  ],
  "type": "registry:ui"
}