{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progress-card",
  "type": "registry:component",
  "title": "Progress Card",
  "description": "Card displaying progress metrics and status.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/progress-card/progress-card.tsx",
      "content": "\"use client\";\n\nimport { memo, useEffect, useState } from \"react\";\n\nimport type { ReactNode } from \"react\";\n\nimport { useMounted } from \"@vllnt/ui\";\nimport { Badge } from \"@vllnt/ui\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@vllnt/ui\";\n\nexport type ContentCardProgress = {\n  completedCount: number;\n  totalSections: number;\n};\n\nexport type ContentCardProps = {\n  /** Badge label for difficulty/category */\n  badgeLabel: string;\n  /** Badge variant */\n  badgeVariant?: \"default\" | \"destructive\" | \"outline\" | \"secondary\";\n  /** Card description */\n  description: string;\n  /** Function to get progress from storage */\n  getProgress?: () => ContentCardProgress | null;\n  /** Href for the card link */\n  href: string;\n  /** Link component to use (e.g., Next.js Link) */\n  linkComponent?: React.ComponentType<{\n    children: ReactNode;\n    className?: string;\n    href: string;\n  }>;\n  /** Metadata items (e.g., \"30 min\", \"10 sections\") */\n  metadata?: string[];\n  /** Progress completed label (e.g., \"completed\") */\n  progressLabel?: string;\n  /** Tags to display */\n  tags?: string[];\n  /** Card title */\n  title: string;\n};\n\nfunction DefaultLink({\n  children,\n  className,\n  href,\n}: {\n  children: ReactNode;\n  className?: string;\n  href: string;\n}): React.ReactNode {\n  return (\n    <a className={className} href={href}>\n      {children}\n    </a>\n  );\n}\n\nconst EMPTY_PROGRESS_CARD_LIST: string[] = [];\n\nfunction ContentCardImpl({\n  badgeLabel,\n  badgeVariant = \"default\",\n  description,\n  getProgress,\n  href,\n  linkComponent: LinkComponent = DefaultLink,\n  metadata = EMPTY_PROGRESS_CARD_LIST,\n  progressLabel = \"completed\",\n  tags = EMPTY_PROGRESS_CARD_LIST,\n  title,\n}: ContentCardProps): React.ReactNode {\n  const [progress, setProgress] = useState<ContentCardProgress | null>(null);\n  const isHydrated = useMounted();\n\n  // Load progress after hydration\n  useEffect(() => {\n    if (getProgress) {\n      const result = getProgress();\n      requestAnimationFrame(() => {\n        setProgress(result);\n      });\n    }\n  }, [getProgress]);\n\n  const showProgress = isHydrated && progress && progress.completedCount > 0;\n\n  return (\n    <LinkComponent className=\"block h-full\" href={href}>\n      <Card className=\"h-full flex flex-col hover:shadow-lg transition-shadow cursor-pointer\">\n        <CardHeader>\n          {/* Badge and progress */}\n          <div className=\"flex items-center gap-2 mb-2\">\n            <Badge className=\"text-xs capitalize\" variant={badgeVariant}>\n              {badgeLabel}\n            </Badge>\n            {showProgress ? (\n              <span className=\"text-xs text-muted-foreground\">\n                {progress.completedCount}/{progress.totalSections}{\" \"}\n                {progressLabel}\n              </span>\n            ) : null}\n          </div>\n\n          <CardTitle className=\"line-clamp-2 text-lg\">{title}</CardTitle>\n          <CardDescription className=\"line-clamp-3\">\n            {description}\n          </CardDescription>\n        </CardHeader>\n\n        <CardContent className=\"mt-auto space-y-2\">\n          {/* Metadata */}\n          {metadata.length > 0 ? (\n            <div className=\"flex flex-wrap gap-2 text-xs text-muted-foreground\">\n              {metadata.map((item, index) => (\n                <span key={item}>\n                  {index > 0 ? <span className=\"mr-2\">•</span> : null}\n                  {item}\n                </span>\n              ))}\n            </div>\n          ) : null}\n\n          {/* Tags */}\n          {tags.length > 0 ? (\n            <div className=\"flex flex-wrap gap-1\">\n              {tags.map((tag) => (\n                <Badge className=\"text-xs\" key={tag} variant=\"outline\">\n                  {tag}\n                </Badge>\n              ))}\n            </div>\n          ) : null}\n        </CardContent>\n      </Card>\n    </LinkComponent>\n  );\n}\n\nexport const ContentCard = memo(ContentCardImpl);\nContentCard.displayName = \"ContentCard\";\n",
      "type": "registry:component"
    }
  ],
  "version": "0.2.1",
  "stability": "stable"
}
