{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "system-states",
    "finance",
    "accounting"
  ],
  "dependencies": [],
  "description": "Structural, per-component.",
  "files": [
    {
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/ledger/cn\";\n\nexport interface SkeletonProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  height?: number | string;\n  radius?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n  width?: number | string;\n}\n\n/**\n * Structural, matching the exact shape, position and radii of what it\n * replaces. A slow breathe is permitted; a shimmer sweep is not — a\n * translating gradient across a full-page skeleton is the clearest\n * template tell there is.\n */\nexport const Skeleton = React.forwardRef<HTMLDivElement, SkeletonProps>(\n  ({ className, width, height = 16, radius = \"xs\", ...props }, ref) => (\n    <div\n      aria-hidden=\"true\"\n      className={cn(\"ledger-breathe bg-surface-sunken\", `rounded-${radius}`, className)}\n      ref={ref}\n      style={{ height, width }}\n      {...props}\n    />\n  ),\n);\nSkeleton.displayName = \"Skeleton\";\n\n/**\n * The figure block reserves the exact figure width, or the card jumps when\n * the data lands — and that jump is worse than no skeleton at all.\n */\nexport function KpiCardSkeleton({ className }: { className?: string }) {\n  return (\n    <div\n      aria-busy=\"true\"\n      aria-label=\"Loading metric\"\n      className={cn(\"rounded-xl border border-border bg-surface p-6\", className)}\n      role=\"status\"\n    >\n      <Skeleton height={16} width={112} />\n      <Skeleton className=\"mt-2\" height={32} radius=\"sm\" width={168} />\n      <Skeleton className=\"mt-2\" height={16} width={136} />\n    </div>\n  );\n}\n\nexport function TableSkeleton({ rows = 6, className }: { rows?: number; className?: string }) {\n  return (\n    <div aria-busy=\"true\" className={cn(\"rounded-xl border border-border bg-surface\", className)}>\n      {Array.from({ length: rows }, (_, i) => (\n        <div\n          className=\"flex h-10 items-center gap-4 border-b border-border-subtle px-4 last:border-b-0\"\n          key={i}\n        >\n          <Skeleton height={12} width={64} />\n          <Skeleton height={12} width=\"35%\" />\n          <Skeleton className=\"ml-auto\" height={12} width={80} />\n        </div>\n      ))}\n    </div>\n  );\n}\n\nexport function StatementSkeleton({ className }: { className?: string }) {\n  return (\n    <div aria-busy=\"true\" className={cn(\"space-y-2\", className)}>\n      {[80, 60, 70, 55, 90].map((w, i) => (\n        <div className=\"flex items-center justify-between gap-8\" key={i}>\n          <Skeleton className=\"max-w-[220px]\" height={12} width={`${w}%`} />\n          <Skeleton height={12} width={72} />\n        </div>\n      ))}\n    </div>\n  );\n}\n",
      "path": "components/ledger/skeleton.tsx",
      "target": "components/ledger/skeleton.tsx",
      "type": "registry:component"
    }
  ],
  "name": "skeleton",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/cn"
  ],
  "title": "Skeleton",
  "type": "registry:component"
}
