{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "empty-state",
  "title": "Empty State",
  "description": "Empty state component with icon, title, description, and optional actions",
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [
    "@boldkit/utils",
    "@boldkit/button"
  ],
  "files": [
    {
      "path": "registry/default/ui/empty-state.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'\nimport {\n  FileQuestion,\n  Search,\n  Inbox,\n  FolderOpen,\n  Users,\n  ShoppingCart,\n  Bell,\n  Image,\n  AlertTriangle,\n  WifiOff,\n  ShieldX,\n  Clock,\n  Wrench,\n  Upload,\n} from 'lucide-react'\n\n// ============================================================================\n// Empty State Root\n// ============================================================================\n\nconst emptyStateVariants = cva(\n  'flex items-center justify-center',\n  {\n    variants: {\n      variant: {\n        default: '',\n        filled: 'bg-muted/30 border-3 border-dashed border-foreground p-8',\n        card: 'bg-card border-3 border-foreground shadow-[4px_4px_0px_hsl(var(--shadow-color))] p-8',\n      },\n      size: {\n        compact: 'gap-2 p-2',\n        sm: 'gap-3 p-4',\n        md: 'gap-4 p-6',\n        lg: 'gap-6 p-8',\n      },\n      layout: {\n        vertical: 'flex-col text-center',\n        horizontal: 'flex-row text-left',\n      },\n      animation: {\n        none: '',\n        fadeIn: 'animate-[fadeIn_0.3s_ease-out]',\n        bounce: 'animate-[bounceIn_0.5s_ease-out]',\n        scale: 'animate-[scaleIn_0.3s_ease-out]',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'md',\n      layout: 'vertical',\n      animation: 'none',\n    },\n  }\n)\n\nexport interface EmptyStateProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof emptyStateVariants> {}\n\nconst EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(\n  ({ className, variant, size, layout, animation, children, ...props }, ref) => {\n    return (\n      <div\n        ref={ref}\n        className={cn(emptyStateVariants({ variant, size, layout, animation }), className)}\n        {...props}\n      >\n        {children}\n      </div>\n    )\n  }\n)\nEmptyState.displayName = 'EmptyState'\n\n// ============================================================================\n// Empty State Icon\n// ============================================================================\n\nconst iconContainerVariants = cva(\n  'flex items-center justify-center border-3 border-foreground shadow-[3px_3px_0px_hsl(var(--shadow-color))]',\n  {\n    variants: {\n      size: {\n        xs: 'w-10 h-10',\n        sm: 'w-12 h-12',\n        md: 'w-16 h-16',\n        lg: 'w-20 h-20',\n        xl: 'w-24 h-24',\n      },\n      iconColor: {\n        default: 'bg-muted text-foreground',\n        primary: 'bg-primary text-primary-foreground',\n        secondary: 'bg-secondary text-secondary-foreground',\n        accent: 'bg-accent text-accent-foreground',\n        muted: 'bg-muted text-muted-foreground',\n        destructive: 'bg-destructive text-destructive-foreground',\n        warning: 'bg-warning text-warning-foreground',\n        success: 'bg-success text-success-foreground',\n      },\n    },\n    defaultVariants: {\n      size: 'md',\n      iconColor: 'default',\n    },\n  }\n)\n\nconst iconSizeMap = {\n  xs: 'h-5 w-5',\n  sm: 'h-6 w-6',\n  md: 'h-8 w-8',\n  lg: 'h-10 w-10',\n  xl: 'h-12 w-12',\n}\n\nexport interface EmptyStateIconProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof iconContainerVariants> {\n  /** Custom icon size independent of container */\n  iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n}\n\nconst EmptyStateIcon = React.forwardRef<HTMLDivElement, EmptyStateIconProps>(\n  ({ className, size, iconColor, iconSize, children, ...props }, ref) => {\n    return (\n      <div\n        ref={ref}\n        className={cn(iconContainerVariants({ size, iconColor }), className)}\n        {...props}\n      >\n        {React.isValidElement(children)\n          ? React.cloneElement(children as React.ReactElement<{ className?: string }>, {\n              className: cn(\n                iconSizeMap[iconSize ?? size ?? 'md'],\n                (children as React.ReactElement<{ className?: string }>).props.className\n              ),\n            })\n          : children}\n      </div>\n    )\n  }\n)\nEmptyStateIcon.displayName = 'EmptyStateIcon'\n\n// ============================================================================\n// Empty State Illustration (for custom SVGs/images)\n// ============================================================================\n\nexport interface EmptyStateIllustrationProps extends React.HTMLAttributes<HTMLDivElement> {\n  /** Max width for the illustration */\n  maxWidth?: string | number\n}\n\nconst EmptyStateIllustration = React.forwardRef<HTMLDivElement, EmptyStateIllustrationProps>(\n  ({ className, maxWidth = '200px', children, style, ...props }, ref) => {\n    return (\n      <div\n        ref={ref}\n        className={cn('flex items-center justify-center', className)}\n        style={{ maxWidth, ...style }}\n        {...props}\n      >\n        {children}\n      </div>\n    )\n  }\n)\nEmptyStateIllustration.displayName = 'EmptyStateIllustration'\n\n// ============================================================================\n// Empty State Title\n// ============================================================================\n\nexport type EmptyStateTitleProps = React.HTMLAttributes<HTMLHeadingElement>\n\nconst EmptyStateTitle = React.forwardRef<HTMLHeadingElement, EmptyStateTitleProps>(\n  ({ className, children, ...props }, ref) => {\n    return (\n      <h3\n        ref={ref}\n        className={cn('font-black text-lg uppercase tracking-wide', className)}\n        {...props}\n      >\n        {children}\n      </h3>\n    )\n  }\n)\nEmptyStateTitle.displayName = 'EmptyStateTitle'\n\n// ============================================================================\n// Empty State Description\n// ============================================================================\n\nexport type EmptyStateDescriptionProps = React.HTMLAttributes<HTMLParagraphElement>\n\nconst EmptyStateDescription = React.forwardRef<HTMLParagraphElement, EmptyStateDescriptionProps>(\n  ({ className, children, ...props }, ref) => {\n    return (\n      <p\n        ref={ref}\n        className={cn('text-muted-foreground font-medium max-w-sm', className)}\n        {...props}\n      >\n        {children}\n      </p>\n    )\n  }\n)\nEmptyStateDescription.displayName = 'EmptyStateDescription'\n\n// ============================================================================\n// Empty State Actions\n// ============================================================================\n\nexport type EmptyStateActionsProps = React.HTMLAttributes<HTMLDivElement>\n\nconst EmptyStateActions = React.forwardRef<HTMLDivElement, EmptyStateActionsProps>(\n  ({ className, children, ...props }, ref) => {\n    return (\n      <div\n        ref={ref}\n        className={cn('flex flex-wrap items-center justify-center gap-2 mt-2', className)}\n        {...props}\n      >\n        {children}\n      </div>\n    )\n  }\n)\nEmptyStateActions.displayName = 'EmptyStateActions'\n\n// ============================================================================\n// Presets\n// ============================================================================\n\nexport type EmptyStatePresetType =\n  | 'no-results'\n  | 'no-data'\n  | 'empty-inbox'\n  | 'empty-folder'\n  | 'no-users'\n  | 'empty-cart'\n  | 'no-notifications'\n  | 'no-images'\n  // New presets\n  | 'error'\n  | 'offline'\n  | 'permission-denied'\n  | 'coming-soon'\n  | 'maintenance'\n  | 'upload'\n\ninterface PresetConfig {\n  icon: React.ReactNode\n  title: string\n  description: string\n  iconColor?: VariantProps<typeof iconContainerVariants>['iconColor']\n}\n\nconst presetIconSizeMap: Record<string, 'xs' | 'sm' | 'md' | 'lg' | 'xl'> = {\n  compact: 'sm',\n  sm: 'sm',\n  md: 'md',\n  lg: 'lg',\n  xl: 'xl',\n  xs: 'xs',\n}\n\nconst presetConfig: Record<EmptyStatePresetType, PresetConfig> = {\n  'no-results': {\n    icon: <Search />,\n    title: 'No results found',\n    description: 'Try adjusting your search or filter to find what you\\'re looking for.',\n  },\n  'no-data': {\n    icon: <FileQuestion />,\n    title: 'No data available',\n    description: 'There\\'s nothing to display here yet. Data will appear once available.',\n  },\n  'empty-inbox': {\n    icon: <Inbox />,\n    title: 'Inbox is empty',\n    description: 'You\\'re all caught up! New messages will appear here.',\n  },\n  'empty-folder': {\n    icon: <FolderOpen />,\n    title: 'Folder is empty',\n    description: 'This folder doesn\\'t contain any files yet.',\n  },\n  'no-users': {\n    icon: <Users />,\n    title: 'No users found',\n    description: 'There are no users matching your criteria.',\n  },\n  'empty-cart': {\n    icon: <ShoppingCart />,\n    title: 'Your cart is empty',\n    description: 'Looks like you haven\\'t added anything to your cart yet.',\n  },\n  'no-notifications': {\n    icon: <Bell />,\n    title: 'No notifications',\n    description: 'You\\'re all caught up! Check back later for updates.',\n  },\n  'no-images': {\n    icon: <Image />,\n    title: 'No images',\n    description: 'There are no images to display. Upload some to get started.',\n  },\n  // New presets\n  'error': {\n    icon: <AlertTriangle />,\n    title: 'Something went wrong',\n    description: 'An error occurred. Please try again or contact support if the problem persists.',\n    iconColor: 'destructive',\n  },\n  'offline': {\n    icon: <WifiOff />,\n    title: 'You\\'re offline',\n    description: 'Please check your internet connection and try again.',\n    iconColor: 'warning',\n  },\n  'permission-denied': {\n    icon: <ShieldX />,\n    title: 'Access denied',\n    description: 'You don\\'t have permission to view this content.',\n    iconColor: 'destructive',\n  },\n  'coming-soon': {\n    icon: <Clock />,\n    title: 'Coming soon',\n    description: 'This feature is under development. Stay tuned for updates!',\n    iconColor: 'accent',\n  },\n  'maintenance': {\n    icon: <Wrench />,\n    title: 'Under maintenance',\n    description: 'We\\'re performing scheduled maintenance. Please check back soon.',\n    iconColor: 'warning',\n  },\n  'upload': {\n    icon: <Upload />,\n    title: 'Upload files',\n    description: 'Drag and drop files here, or click to browse.',\n    iconColor: 'primary',\n  },\n}\n\nexport interface EmptyStatePresetProps\n  extends Omit<EmptyStateProps, 'children'>,\n    Omit<VariantProps<typeof iconContainerVariants>, 'size'> {\n  preset: EmptyStatePresetType\n  action?: React.ReactNode\n  customTitle?: string\n  customDescription?: string\n  /** Custom icon to override the preset icon */\n  customIcon?: React.ReactNode\n  /** Custom illustration (overrides icon completely) */\n  illustration?: React.ReactNode\n  /** Icon container size */\n  iconSize?: VariantProps<typeof iconContainerVariants>['size']\n}\n\nconst EmptyStatePreset = React.forwardRef<HTMLDivElement, EmptyStatePresetProps>(\n  (\n    {\n      preset,\n      action,\n      customTitle,\n      customDescription,\n      customIcon,\n      illustration,\n      iconColor,\n      iconSize,\n      size,\n      layout,\n      variant,\n      animation,\n      className,\n      ...props\n    },\n    ref\n  ) => {\n    const config = presetConfig[preset]\n    const finalIconColor = iconColor ?? config.iconColor ?? 'default'\n\n    return (\n      <EmptyState\n        ref={ref}\n        variant={variant}\n        size={size}\n        layout={layout}\n        animation={animation}\n        className={className}\n        {...props}\n      >\n        {illustration ? (\n          <EmptyStateIllustration>{illustration}</EmptyStateIllustration>\n        ) : (\n          <EmptyStateIcon iconColor={finalIconColor} size={iconSize ?? presetIconSizeMap[size ?? 'md'] ?? 'md'}>\n            {customIcon ?? config.icon}\n          </EmptyStateIcon>\n        )}\n        <div className={cn(layout === 'horizontal' && 'flex flex-col')}>\n          <EmptyStateTitle>{customTitle ?? config.title}</EmptyStateTitle>\n          <EmptyStateDescription>{customDescription ?? config.description}</EmptyStateDescription>\n          {action && <EmptyStateActions>{action}</EmptyStateActions>}\n        </div>\n      </EmptyState>\n    )\n  }\n)\nEmptyStatePreset.displayName = 'EmptyStatePreset'\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n  EmptyState,\n  EmptyStateIcon,\n  EmptyStateIllustration,\n  EmptyStateTitle,\n  EmptyStateDescription,\n  EmptyStateActions,\n  EmptyStatePreset,\n  emptyStateVariants,\n  iconContainerVariants,\n}\n",
      "type": "registry:ui",
      "target": "components/ui/empty-state.tsx"
    }
  ],
  "type": "registry:ui"
}