{
  "name": "empty",
  "type": "registry:ui",
  "title": "Empty",
  "description": "Empty explains a genuine no-content state and can provide a clear next action.",
  "registryDependencies": [
    "@siteplane/base"
  ],
  "dependencies": [
    "class-variance-authority@0.7.1"
  ],
  "files": [
    {
      "path": "src/components/ui/empty.tsx",
      "type": "registry:ui",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport type React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst emptyMediaVariants = cva(\n  \"flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  {\n    defaultVariants: {\n      variant: \"default\",\n    },\n    variants: {\n      variant: {\n        default: \"bg-transparent\",\n        icon: \"relative flex size-9 shrink-0 items-center justify-center rounded-md border bg-card not-dark:bg-clip-padding text-foreground shadow-sm/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5\",\n      },\n    },\n  },\n);\n\nexport function Empty({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n  return (\n    <div\n      className={cn(\n        \"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance px-6 py-12 text-center md:py-20\",\n        className,\n      )}\n      data-slot=\"empty\"\n      {...props}\n    />\n  );\n}\n\nexport function EmptyHeader({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n  return (\n    <div\n      className={cn(\n        \"flex max-w-sm flex-col items-center text-center\",\n        className,\n      )}\n      data-slot=\"empty-header\"\n      {...props}\n    />\n  );\n}\n\nexport function EmptyMedia({\n  className,\n  variant = \"default\",\n  ...props\n}: React.ComponentProps<\"div\"> &\n  VariantProps<typeof emptyMediaVariants>): React.ReactElement {\n  return (\n    <div\n      className={cn(\"relative mb-6\", className)}\n      data-slot=\"empty-media\"\n      data-variant={variant}\n      {...props}\n    >\n      {variant === \"icon\" && (\n        <>\n          <div\n            aria-hidden=\"true\"\n            className={cn(\n              emptyMediaVariants({ variant }),\n              className,\n              \"pointer-events-none absolute bottom-px origin-bottom-left -translate-x-0.5 -rotate-10 scale-84 shadow-none\",\n            )}\n          />\n          <div\n            aria-hidden=\"true\"\n            className={cn(\n              emptyMediaVariants({ variant }),\n              className,\n              \"pointer-events-none absolute bottom-px origin-bottom-right translate-x-0.5 rotate-10 scale-84 shadow-none\",\n            )}\n          />\n        </>\n      )}\n      <div\n        className={cn(emptyMediaVariants({ variant }), className)}\n        {...props}\n      />\n    </div>\n  );\n}\n\nexport function EmptyTitle({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n  return (\n    <div\n      className={cn(\"font-heading font-semibold text-xl\", className)}\n      data-slot=\"empty-title\"\n      {...props}\n    />\n  );\n}\n\nexport function EmptyDescription({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n  return (\n    <div\n      className={cn(\n        \"text-muted-foreground text-sm [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1\",\n        className,\n      )}\n      data-slot=\"empty-description\"\n      {...props}\n    />\n  );\n}\n\nexport function EmptyContent({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">): React.ReactElement {\n  return (\n    <div\n      className={cn(\n        \"flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm\",\n        className,\n      )}\n      data-slot=\"empty-content\"\n      {...props}\n    />\n  );\n}\n"
    }
  ],
  "categories": [
    "feedback"
  ],
  "docs": "# Empty\n\n> Siteplane UI release `0.1.1`.\n\n## Public Purpose\n\nEmpty explains a genuine no-content state and can offer a clear next action. Use\nSkeleton for loading and Alert for an error that still has surrounding content.\n\n## Import\n\n`import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from \"@/components/ui/empty\";`\n\n## Public API\n\n- Compose `EmptyHeader`, optional `EmptyMedia`, `EmptyTitle`,\n  `EmptyDescription`, and optional `EmptyContent`.\n- A direct anchor inside `EmptyDescription` receives the native inline-link\n  underline and hover treatment.\n- Put a primary recovery or creation action in `EmptyContent`; omit it when\n  there is no meaningful next step.\n\n## Public Motion\n\n- Empty has no mount or exit animation.\n- Actions use their own Button or link motion; do not animate the entire state.\n\n## Public Accessibility\n\n- State plainly why no content is available.\n- Give the optional action an explicit label that describes its result.\n- Use meaningful media only as supporting context; never rely on the illustration\n  or color alone.\n- Keep inline links semantic and keyboard focusable.\n\n## Public Agent Guidance\n\n- Use Empty only for a real zero-data state, not loading, error, or permission\n  denial by default.\n- Keep copy concise and action-oriented.\n- Compose existing slots instead of creating a parallel empty-state primitive.\n\n## Public Links\n\n- [Documentation and preview](https://ui.siteplane.io/docs/components/feedback/empty)\n\n- [Registry source](https://ui.siteplane.io/r/empty.json)\n",
  "meta": {
    "siteplane:agentContractVersion": 1,
    "siteplane:docs": "https://ui.siteplane.io/docs/components/feedback/empty",
    "siteplane:releaseVersion": "0.1.1",
    "siteplane:sourceOwned": true
  },
  "devDependencies": []
}
