{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "content-blocks",
  "title": "Content Blocks",
  "author": "Ben Hofstetter <ben.hofstetter@gmail.com>",
  "description": "A self-contained block renderer for markdown, images, galleries, video, embeds, links, and callouts. Pass an array of blocks, get structured content.",
  "type": "registry:component",
  "categories": [
    "snax"
  ],
  "dependencies": [
    "react-markdown"
  ],
  "files": [
    {
      "path": "src/registry/components/content-blocks/content-blocks.tsx",
      "content": "\"use client\"\n\nimport { cn } from \"@/lib/utils\"\nimport ReactMarkdown from \"react-markdown\"\n\nexport type ContentBlockData = {\n  type: \"markdown\" | \"image\" | \"gallery\" | \"video\" | \"embed\" | \"link\" | \"callout\"\n  content?: string\n  url?: string\n  alt?: string\n  images?: string[]\n  title?: string\n}\n\nexport function ContentBlocks({\n  blocks = [],\n  className,\n}: React.ComponentProps<\"div\"> & {\n  blocks: ContentBlockData[]\n}) {\n  return (\n    <div className={cn(\"space-y-6\", className)}>\n      {blocks.map((block, index) => {\n        switch (block.type) {\n          case \"markdown\":\n            return (\n              <div key={index} className=\"prose prose-sm max-w-none dark:prose-invert\">\n                <ReactMarkdown>{block.content || \"\"}</ReactMarkdown>\n              </div>\n            )\n          case \"image\":\n            return (\n              <figure key={index} className=\"overflow-hidden rounded-lg border\">\n                <img src={block.url} alt={block.alt || \"\"} className=\"w-full\" />\n                {block.alt && (\n                  <figcaption className=\"px-3 py-2 text-xs text-muted-foreground\">{block.alt}</figcaption>\n                )}\n              </figure>\n            )\n          case \"gallery\":\n            return (\n              <div key={index} className=\"grid grid-cols-2 gap-2 sm:grid-cols-3\">\n                {(block.images || []).map((img, i) => (\n                  <img key={i} src={img} alt=\"\" className=\"aspect-square w-full rounded-lg border object-cover\" />\n                ))}\n              </div>\n            )\n          case \"video\":\n            return (\n              <div key={index} className=\"overflow-hidden rounded-lg border\">\n                <video src={block.url} controls className=\"w-full\" />\n              </div>\n            )\n          case \"embed\":\n            return (\n              <div key={index} className=\"overflow-hidden rounded-lg border\">\n                <iframe src={block.url} className=\"aspect-video w-full\" title={block.title || \"Embedded content\"} />\n              </div>\n            )\n          case \"link\":\n            return (\n              <a\n                key={index}\n                href={block.url}\n                target=\"_blank\"\n                rel=\"noopener noreferrer\"\n                className=\"block rounded-lg border p-3 transition-all hover:border-foreground\"\n              >\n                <p className=\"text-sm font-medium\">{block.title || block.url}</p>\n                <p className=\"mt-0.5 text-xs text-muted-foreground\">{block.url}</p>\n              </a>\n            )\n          case \"callout\":\n            return (\n              <div key={index} className=\"rounded-lg border border-foreground/20 bg-muted/50 p-4\">\n                <p className=\"text-sm\">{block.content}</p>\n              </div>\n            )\n          default:\n            return null\n        }\n      })}\n    </div>\n  )\n}",
      "type": "registry:component",
      "target": "@components/content-blocks.tsx"
    }
  ]
}