{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "empty-state",
  "title": "Empty State",
  "description": "Empty State from the Get IT Done design system.",
  "dependencies": [
    "class-variance-authority@^0.7.0",
    "lucide-react@^0.379.0"
  ],
  "registryDependencies": [
    "https://zero-design.itdone.de/r/utils.json",
    "https://zero-design.itdone.de/r/theme.json"
  ],
  "files": [
    {
      "path": "registry/ui/empty-state.tsx",
      "content": "'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { AlertCircle, Inbox, Lock, Search } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\n// Figma: Empty state 1182:317. Variant=First-use|No-results|Error|No-access (dashed, compact tile) and Variant=Default (sizes sm|md|lg, color, icon kind).\nconst emptyStateVariants = cva('flex w-full flex-col', {\n  variants: {\n    // center is the default. start aligns tile, text and actions to the start edge, for page level states beside left aligned content.\n    align: {\n      center: 'items-center text-center',\n      start: 'items-start text-left',\n    },\n    variant: {\n      default: '',\n      'first-use': '',\n      'no-results': '',\n      error: '',\n      'no-access': '',\n    },\n    size: {\n      // Lighter than sm for small cards: tighter gap, smaller tile and title.\n      xs: 'gap-3',\n      sm: 'gap-6',\n      md: 'gap-8',\n      lg: 'gap-8',\n      // Page level (404, access denied, first run of a whole page): lg spacing and tile with the page title type role.\n      page: 'gap-8',\n    },\n  },\n  compoundVariants: [\n    {\n      variant: ['first-use', 'no-results', 'error', 'no-access'],\n      className: 'gap-2 rounded-surface border border-dashed border-border px-6 py-10',\n    },\n  ],\n  defaultVariants: { variant: 'default', size: 'sm', align: 'center' },\n});\n\nconst DEFAULT_ICONS = {\n  default: Search,\n  'first-use': Inbox,\n  'no-results': Search,\n  error: AlertCircle,\n  'no-access': Lock,\n} as const;\n\nexport interface EmptyStateProps\n  extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'>,\n    VariantProps<typeof emptyStateVariants> {\n  title: React.ReactNode;\n  // Element of the title. Defaults to a paragraph; use a heading level for pages like 404 or access denied (size=\"page\" sets the page title type role).\n  // `display` sets the title in the display-sm role (32px, the closest token step to a 36px title). Default keeps the role of the size.\n  titleSize?: 'default' | 'display';\n  titleAs?: 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n  // Text or nodes. Plain text renders as one paragraph. Pass your own paragraphs as a node (rendered in a block), or use `children` for several.\n  description?: React.ReactNode;\n  // Short line above the title, for example \"404\" or an error code.\n  kicker?: React.ReactNode;\n  // Further content below the description, for example additional paragraphs.\n  children?: React.ReactNode;\n  // Overrides the variant's default glyph. Pass null to render no icon.\n  icon?: React.ReactNode;\n  // Replaces the icon tile with a larger illustration (see Illustration).\n  illustration?: React.ReactNode;\n  // Featured icon colour for the default variant.\n  tone?: 'primary' | 'gray';\n  // Action buttons. Stacked and centered for the four state variants, in a row for default.\n  actions?: React.ReactNode;\n}\n\nconst EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(\n  ({ className, variant = 'default', size = 'sm', tone = 'gray', title, titleAs = 'p', titleSize = 'default', description, kicker, icon, illustration, actions, role, align = 'center', children, ...props }, ref) => {\n    const start = align === 'start';\n    const isState = variant !== 'default';\n    const Fallback = DEFAULT_ICONS[variant ?? 'default'];\n    const glyph = icon === undefined ? <Fallback className=\"h-icon-md w-icon-md\" aria-hidden=\"true\" /> : icon;\n    const resolvedRole = role ?? (variant === 'error' ? 'alert' : 'status');\n\n    const tile = illustration ? (\n      illustration\n    ) : glyph === null ? null : isState ? (\n      <span className=\"flex h-avatar-md w-avatar-md items-center justify-center rounded-control bg-muted text-icon-subtle\">{glyph}</span>\n    ) : (\n      <span\n        className={cn(\n          'flex items-center justify-center rounded-full border-solid text-icon-default',\n          size === 'lg' || size === 'page' ? 'h-avatar-xl w-avatar-xl border-8' : size === 'xs' ? 'h-avatar-md w-avatar-md border-4' : 'h-avatar-lg w-avatar-lg border-8',\n          tone === 'primary'\n            ? 'border-background-brand-subtle bg-background-brand-subtle text-icon-brand'\n            : 'border-border-subtle bg-background-neutral-default',\n        )}\n      >\n        {glyph}\n      </span>\n    );\n\n    const Title = titleAs;\n\n    return (\n      <div ref={ref} role={resolvedRole} className={cn(emptyStateVariants({ variant, size, align }), className)} {...props}>\n        {tile}\n        <div className={cn('flex w-full flex-col', start ? 'items-start' : 'items-center', isState ? 'max-w-sm gap-1' : size === 'sm' || size === 'xs' ? 'max-w-sm gap-1' : 'max-w-sm gap-2')}>\n          {kicker ? (\n            <p data-slot=\"kicker\" className=\"typography-ui-semibold m-0 text-text-subtle\">\n              {kicker}\n            </p>\n          ) : null}\n          <Title data-slot=\"title\" className={cn('text-text-default', titleSize === 'display' ? 'typography-display-sm' : size === 'page' ? 'typography-page-title' : size === 'xs' ? 'typography-label-highlight' : isState || size === 'sm' ? 'typography-ui-lg-semibold' : 'typography-label-highlight')}>\n            {title}\n          </Title>\n          {description ? (\n            typeof description === 'string' || typeof description === 'number' ? (\n              <p data-slot=\"description\" className={cn('text-text-subtle', isState ? 'typography-ui' : 'typography-small')}>{description}</p>\n            ) : (\n              <div data-slot=\"description\" className={cn('flex flex-col gap-2 text-text-subtle [&>p]:m-0', isState ? 'typography-ui' : 'typography-small')}>{description}</div>\n            )\n          ) : null}\n          {children ? <div data-slot=\"content\" className={cn('flex flex-col gap-2 text-text-subtle [&>p]:m-0', isState ? 'typography-ui' : 'typography-small')}>{children}</div> : null}\n        </div>\n        {actions ? <div className={cn('flex', isState ? 'flex-col gap-2' : cn('flex-wrap gap-3', start ? 'items-start justify-start' : 'items-center justify-center'), isState && (start ? 'items-start' : 'items-center'))}>{actions}</div> : null}\n      </div>\n    );\n  },\n);\nEmptyState.displayName = 'EmptyState';\n\nexport { EmptyState, emptyStateVariants };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}