{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ds-contribution-graph",
  "title": "Contribution Graph",
  "description": "Graph estilo GitHub 7x20 — adaptado Kibo.",
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@lema-ds/skeleton",
    "@lema-ds/ui-i18n",
    "@lema-ds/ds-locale-provider",
    "@lema-ds/tokens"
  ],
  "files": [
    {
      "path": "components/ds/ds-contribution-graph.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { UI_I18N, type UILocale } from \"@/lib/ui-i18n\"\nimport { useUILocale } from \"@/components/ui/ds-locale-provider\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport interface ContributionGraphProps\n  extends\n    React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof contributionGraphVariants> {\n  data?: number[][] // 7 x weeks\n  locale?: UILocale\n  loading?: boolean\n}\n\n// ── Variants ───────────────────────────────────────────────────────────────\n\nexport const contributionGraphVariants = cva(\n  \"flex flex-col gap-2 rounded-2xl border bg-card p-4\",\n  {\n    variants: {\n      size: {\n        sm: \"[&>div>div]:size-2.5\",\n        md: \"[&>div>div]:size-3\",\n      },\n    },\n    defaultVariants: { size: \"md\" },\n  }\n)\n\nconst levelClasses = [\n  \"bg-muted\",\n  \"bg-success/20\",\n  \"bg-success/40\",\n  \"bg-success/70\",\n  \"bg-success\",\n]\n\n// ── Component ──────────────────────────────────────────────────────────────\n\nexport function ContributionGraph({\n  className,\n  data,\n  locale: localeProp,\n  size = \"md\",\n  loading = false,\n  ...props\n}: ContributionGraphProps) {\n  const locale = useUILocale(localeProp)\n  const weeks = React.useMemo(\n    () =>\n      data ??\n      Array.from({ length: 20 }).map(() =>\n        Array.from({ length: 7 }).map(() => Math.floor(Math.random() * 5))\n      ),\n    [data]\n  )\n  const t = UI_I18N[locale].contributionGraph\n\n  if (loading) {\n    return (\n      <div\n        data-slot=\"contribution-graph-skeleton\"\n        className={cn(contributionGraphVariants({ size }), className)}\n        {...props}\n      >\n        <Skeleton className=\"h-24 w-full\" />\n      </div>\n    )\n  }\n\n  return (\n    <div\n      data-slot=\"contribution-graph\"\n      role=\"img\"\n      aria-label={`Contribution graph: ${t.less} to ${t.more}`}\n      className={cn(contributionGraphVariants({ size }), className)}\n      {...props}\n    >\n      <div className=\"flex gap-1 overflow-x-auto\" aria-hidden=\"true\">\n        {weeks.map((week, wi) => (\n          <div key={wi} className=\"flex flex-col gap-1\">\n            {week.map((level, di) => (\n              <div\n                key={di}\n                aria-hidden=\"true\"\n                title={\n                  level === 0 ? t.noContributions : `${level} contributions`\n                }\n                className={cn(\n                  \"size-3 rounded-sm\",\n                  levelClasses[Math.min(level, 4)]\n                )}\n              />\n            ))}\n          </div>\n        ))}\n      </div>\n      <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n        <span>{t.less}</span>\n        <div className=\"flex gap-1\">\n          {levelClasses.map((c, i) => (\n            <span key={i} className={cn(\"size-3 rounded-sm\", c)} />\n          ))}\n        </div>\n        <span>{t.more}</span>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
