{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "blog-post-card-grid",
  "title": "Blog Post Card Grid",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/blog-post-card-grid/blog-post-card-grid.component.ts",
      "content": "// Modern editorial magazine 3-column article card grid with featured hero story, reading\n// time pills, category filter pills, author avatars, and a newsletter subscription box.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport { ArrowRight, BookOpen, Check, Clock, Loader2, LucideAngularModule, Mail, Star } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiAvatarFallbackComponent, UiAvatarImageComponent, UiAvatarComponent } from '@/ui/avatar/avatar.component'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component'\nimport { UiInputComponent } from '@/ui/input/input.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\n\nexport interface Author {\n  name: string\n  role: string\n  avatar: string\n  initials: string\n}\n\nexport interface BlogPost {\n  id: string\n  title: string\n  excerpt: string\n  category: 'Architecture' | 'Design Systems' | 'Performance' | 'Tutorials'\n  readTime: string\n  date: string\n  image: string\n  author: Author\n}\n\nconst categories = ['All', 'Architecture', 'Design Systems', 'Performance', 'Tutorials'] as const\nexport type BlogCategory = (typeof categories)[number]\n\nconst featuredPost: BlogPost = {\n  id: 'featured-1',\n  title: 'Deconstructing Event-Driven Micro-Frontends at Scale',\n  excerpt:\n    'How we transitioned a monolithic dashboard into decoupled, independently deployable island architectures using web components, resilient event buses, and broadcast channels.',\n  category: 'Architecture',\n  readTime: '8 min read',\n  date: 'Aug 18, 2026',\n  image: 'https://images.unsplash.com/photo-1558494949-ef010cbdcc31?w=1200&auto=format&fit=crop&q=80',\n  author: {\n    name: 'Elena Rostova',\n    role: 'Principal Systems Architect',\n    avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=150&auto=format&fit=crop&q=80',\n    initials: 'ER',\n  },\n}\n\nconst initialPosts: BlogPost[] = [\n  {\n    id: 'post-1',\n    title: 'Architecting Token Hierarchies in Tailwind CSS v4',\n    excerpt:\n      'A comprehensive guide to structured OKLCH color palettes, dynamic light and dark elevation layers, and type scale ergonomics.',\n    category: 'Design Systems',\n    readTime: '5 min read',\n    date: 'Aug 16, 2026',\n    image: 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Marcus Chen',\n      role: 'Design Technologist',\n      avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&auto=format&fit=crop&q=80',\n      initials: 'MC',\n    },\n  },\n  {\n    id: 'post-2',\n    title: 'Eliminating Layout Shift in Hydrated Islands',\n    excerpt:\n      'Techniques for zero-CLS component streaming, skeleton synchronization, and sub-100ms Interaction to Next Paint (INP).',\n    category: 'Performance',\n    readTime: '6 min read',\n    date: 'Aug 14, 2026',\n    image: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Sarah Jenkins',\n      role: 'Performance Engineer',\n      avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=150&auto=format&fit=crop&q=80',\n      initials: 'SJ',\n    },\n  },\n  {\n    id: 'post-3',\n    title: 'Deterministic State Synchronization Over WebSockets',\n    excerpt:\n      'Building conflict-free collaborative data models with operational transformation and CRDTs for multi-tenant SaaS.',\n    category: 'Architecture',\n    readTime: '7 min read',\n    date: 'Aug 11, 2026',\n    image: 'https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Devon Vance',\n      role: 'Distributed Systems Lead',\n      avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=150&auto=format&fit=crop&q=80',\n      initials: 'DV',\n    },\n  },\n  {\n    id: 'post-4',\n    title: 'Building Headless Accessible Dropdowns with Reka UI',\n    excerpt:\n      'Step-by-step implementation of focus trap management, keyboard navigation patterns, and polymorphic slot composition.',\n    category: 'Tutorials',\n    readTime: '4 min read',\n    date: 'Aug 08, 2026',\n    image: 'https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Aaliyah Patel',\n      role: 'Frontend Engineer',\n      avatar: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=150&auto=format&fit=crop&q=80',\n      initials: 'AP',\n    },\n  },\n  {\n    id: 'post-5',\n    title: 'Fluid Typography and Motion Curves in Modern Web Apps',\n    excerpt:\n      'Using CSS clamp functions and spring physics to create tactile, responsive interfaces that adapt directly across devices.',\n    category: 'Design Systems',\n    readTime: '5 min read',\n    date: 'Aug 04, 2026',\n    image: 'https://images.unsplash.com/photo-1507238691740-187a5b1d37b8?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Lucas Meyer',\n      role: 'UI Engineer',\n      avatar: 'https://images.unsplash.com/photo-1519085360753-af0119f7cbe7?w=150&auto=format&fit=crop&q=80',\n      initials: 'LM',\n    },\n  },\n  {\n    id: 'post-6',\n    title: 'Continuous Benchmarking with Playwright and GitHub Actions',\n    excerpt:\n      'Automate regression detection for memory leaks, bundle sizes, and render latency directly within your CI pull request checks.',\n    category: 'Tutorials',\n    readTime: '6 min read',\n    date: 'Jul 30, 2026',\n    image: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Elena Rostova',\n      role: 'Principal Systems Architect',\n      avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=150&auto=format&fit=crop&q=80',\n      initials: 'ER',\n    },\n  },\n]\n\nconst additionalPosts: BlogPost[] = [\n  {\n    id: 'post-7',\n    title: 'Optimizing JavaScript Garbage Collection in High-Frequency Canvas',\n    excerpt:\n      'How object pooling and typed array buffers solved stuttering frame rates during real-time telemetry rendering.',\n    category: 'Performance',\n    readTime: '9 min read',\n    date: 'Jul 26, 2026',\n    image: 'https://images.unsplash.com/photo-1504639725590-34d0984388bd?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Marcus Chen',\n      role: 'Design Technologist',\n      avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&auto=format&fit=crop&q=80',\n      initials: 'MC',\n    },\n  },\n  {\n    id: 'post-8',\n    title: 'Resilient Edge Caching Strategies for Dynamic Multi-Region APIs',\n    excerpt:\n      'Configuring stale-while-revalidate headers, cache tagging, and instant surrogate key purging across worldwide POPs.',\n    category: 'Architecture',\n    readTime: '7 min read',\n    date: 'Jul 22, 2026',\n    image: 'https://images.unsplash.com/photo-1518770660439-4636190af475?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Devon Vance',\n      role: 'Distributed Systems Lead',\n      avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=150&auto=format&fit=crop&q=80',\n      initials: 'DV',\n    },\n  },\n  {\n    id: 'post-9',\n    title: 'Designing High-Contrast Dark Modes without Washing Out Brand Identity',\n    excerpt:\n      'Tuning APCA perceptual contrast ratios, luminance curves, and colored alpha borders in enterprise dark themes.',\n    category: 'Design Systems',\n    readTime: '5 min read',\n    date: 'Jul 18, 2026',\n    image: 'https://images.unsplash.com/photo-1550751827-4bd374c3f58b?w=800&auto=format&fit=crop&q=80',\n    author: {\n      name: 'Aaliyah Patel',\n      role: 'Frontend Engineer',\n      avatar: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=150&auto=format&fit=crop&q=80',\n      initials: 'AP',\n    },\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-blog-post-card-grid, [ui-blog-post-card-grid]',\n  standalone: true,\n  // React renders the root <section> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiAvatarComponent,\n    UiAvatarFallbackComponent,\n    UiAvatarImageComponent,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiInputComponent,\n    UiSeparatorComponent,\n  ],\n  template: `\n    <section data-slot=\"blog-post-card-grid\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-7xl space-y-12 px-4 sm:space-y-16 sm:px-6 lg:px-8\">\n        <!-- Section Header -->\n        <div class=\"flex flex-col items-start justify-between gap-6 md:flex-row md:items-end\">\n          <div class=\"max-w-2xl space-y-3\">\n            <span ui-badge variant=\"outline\" class=\"gap-1.5 px-3 py-1 text-xs font-medium\">\n              <lucide-icon [img]=\"BookOpen\" class=\"text-primary size-3.5\" />\n              From the Blog\n            </span>\n            <h2 class=\"text-foreground text-3xl font-bold tracking-tight sm:text-4xl lg:text-5xl\">\n              Latest Articles &amp; Engineering Deep Dives\n            </h2>\n            <p class=\"text-muted-foreground text-base leading-relaxed sm:text-lg\">\n              Technical essays on software architecture, design systems, and frontend performance.\n            </p>\n          </div>\n\n          <!-- Category Filter Pills -->\n          <div class=\"flex flex-wrap items-center gap-2\" role=\"tablist\" aria-label=\"Article categories\">\n            @for (cat of categories; track cat) {\n              <button\n                ui-button\n                size=\"sm\"\n                [variant]=\"activeCategory() === cat ? 'default' : 'outline'\"\n                class=\"rounded-full text-xs font-medium\"\n                role=\"tab\"\n                [attr.aria-selected]=\"activeCategory() === cat\"\n                (click)=\"handleCategorySelect(cat)\"\n              >\n                {{ cat }}\n              </button>\n            }\n          </div>\n        </div>\n\n        <!-- Featured Hero Article Card -->\n        @if (isHeroVisible()) {\n          <div\n            ui-card\n            class=\"group/hero border-border bg-card hover:border-primary/30 relative overflow-hidden shadow-xs transition-colors duration-300 hover:shadow-md\"\n          >\n            <div class=\"grid grid-cols-1 lg:grid-cols-12\">\n              <div\n                class=\"bg-muted relative aspect-video min-h-[260px] min-w-0 overflow-hidden sm:min-h-[340px] lg:col-span-7 lg:aspect-auto\"\n              >\n                <img\n                  [src]=\"featured.image\"\n                  [alt]=\"featured.title\"\n                  class=\"size-full object-cover transition-transform duration-500 ease-out group-hover/hero:scale-105\"\n                />\n                <div class=\"absolute top-4 left-4 flex flex-wrap items-center gap-2\">\n                  <span\n                    ui-badge\n                    class=\"bg-primary text-primary-foreground border-transparent text-xs font-medium shadow-xs\"\n                  >\n                    <lucide-icon [img]=\"Star\" class=\"mr-1 size-3\" />\n                    Featured Story\n                  </span>\n                  <span\n                    ui-badge\n                    variant=\"secondary\"\n                    class=\"bg-background/90 text-foreground border-border/60 text-xs font-medium shadow-xs backdrop-blur-md\"\n                  >\n                    {{ featured.category }}\n                  </span>\n                </div>\n              </div>\n\n              <div ui-card-content class=\"flex flex-col justify-between space-y-6 p-6 sm:p-8 lg:col-span-5 lg:p-10\">\n                <div class=\"space-y-4\">\n                  <div class=\"text-muted-foreground flex items-center gap-2 text-xs font-medium\">\n                    <lucide-icon [img]=\"BookOpen\" class=\"text-primary size-3.5\" />\n                    <span>Editorial Dispatch</span>\n                    <span>&bull;</span>\n                    <span class=\"inline-flex items-center gap-1\">\n                      <lucide-icon [img]=\"Clock\" class=\"size-3\" />\n                      {{ featured.readTime }}\n                    </span>\n                  </div>\n\n                  <h3\n                    class=\"text-foreground group-hover/hero:text-primary text-2xl leading-tight font-bold tracking-tight transition-colors sm:text-3xl\"\n                  >\n                    <a href=\"#\" class=\"focus-visible:ring-ring focus-visible:underline focus-visible:outline-none\">\n                      {{ featured.title }}\n                    </a>\n                  </h3>\n\n                  <p class=\"text-muted-foreground line-clamp-4 text-sm leading-relaxed sm:text-base\">\n                    {{ featured.excerpt }}\n                  </p>\n                </div>\n\n                <div class=\"space-y-5 pt-2\">\n                  <ui-separator class=\"bg-border/60\" />\n                  <div class=\"flex flex-wrap items-center justify-between gap-4\">\n                    <div class=\"flex items-center gap-3\">\n                      <ui-avatar size=\"default\" class=\"border-border/60 border shadow-xs\">\n                        <ui-avatar-image [src]=\"featured.author.avatar\" [alt]=\"featured.author.name\" />\n                        <ui-avatar-fallback [text]=\"featured.author.initials\" />\n                      </ui-avatar>\n                      <div>\n                        <p class=\"text-foreground text-sm font-semibold\">{{ featured.author.name }}</p>\n                        <p class=\"text-muted-foreground text-xs\">\n                          {{ featured.date }} &middot; {{ featured.author.role }}\n                        </p>\n                      </div>\n                    </div>\n\n                    <button ui-button size=\"sm\" class=\"group/btn gap-1.5\">\n                      <span>Read Article</span>\n                      <lucide-icon\n                        [img]=\"ArrowRight\"\n                        class=\"size-3.5 transition-transform duration-200 group-hover/btn:translate-x-1\"\n                      />\n                    </button>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        }\n\n        <!-- 3-Column Article Card Grid -->\n        @if (visiblePosts().length > 0) {\n          <div class=\"grid grid-cols-1 gap-6 sm:gap-8 md:grid-cols-2 lg:grid-cols-3\">\n            @for (post of visiblePosts(); track post.id) {\n              <div\n                ui-card\n                class=\"group border-border bg-card hover:border-primary/30 flex flex-col justify-between overflow-hidden shadow-xs transition-colors duration-300 hover:shadow-md\"\n              >\n                <div class=\"bg-muted relative aspect-video w-full overflow-hidden\">\n                  <img\n                    [src]=\"post.image\"\n                    [alt]=\"post.title\"\n                    loading=\"lazy\"\n                    class=\"size-full object-cover transition-transform duration-500 ease-out group-hover:scale-105\"\n                  />\n                  <div class=\"absolute top-3 left-3\">\n                    <span\n                      ui-badge\n                      variant=\"secondary\"\n                      class=\"bg-background/85 text-foreground border-border/50 text-xs font-medium shadow-xs backdrop-blur-md\"\n                    >\n                      {{ post.category }}\n                    </span>\n                  </div>\n                </div>\n\n                <div class=\"flex flex-1 flex-col justify-between space-y-4 p-5 sm:p-6\">\n                  <div class=\"space-y-2.5\">\n                    <h3\n                      class=\"text-foreground group-hover:text-primary line-clamp-2 text-lg font-semibold tracking-tight transition-colors\"\n                    >\n                      <a href=\"#\" class=\"focus-visible:ring-ring focus-visible:underline focus-visible:outline-none\">\n                        {{ post.title }}\n                      </a>\n                    </h3>\n                    <p class=\"text-muted-foreground line-clamp-2 text-sm leading-relaxed\">\n                      {{ post.excerpt }}\n                    </p>\n                  </div>\n\n                  <div class=\"space-y-4 pt-2\">\n                    <ui-separator class=\"bg-border/60\" />\n                    <div class=\"flex items-center justify-between gap-3\">\n                      <div class=\"flex min-w-0 items-center gap-2.5\">\n                        <ui-avatar size=\"sm\" class=\"border-border/60 border\">\n                          <ui-avatar-image [src]=\"post.author.avatar\" [alt]=\"post.author.name\" />\n                          <ui-avatar-fallback [text]=\"post.author.initials\" />\n                        </ui-avatar>\n                        <div class=\"min-w-0 flex-1\">\n                          <p class=\"text-foreground truncate text-xs font-medium\">{{ post.author.name }}</p>\n                          <p class=\"text-muted-foreground truncate text-xs\">{{ post.date }}</p>\n                        </div>\n                      </div>\n\n                      <div\n                        class=\"text-muted-foreground bg-muted/60 flex shrink-0 items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium\"\n                      >\n                        <lucide-icon [img]=\"Clock\" class=\"size-3\" />\n                        <span>{{ post.readTime }}</span>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            }\n          </div>\n        } @else {\n          <!-- Empty State When No Posts Match Category -->\n          <div class=\"border-border bg-card/40 space-y-3 rounded-xl border border-dashed p-10 text-center\">\n            <div class=\"bg-muted text-muted-foreground mx-auto flex size-12 items-center justify-center rounded-full\">\n              <lucide-icon [img]=\"BookOpen\" class=\"size-6\" />\n            </div>\n            <h3 class=\"text-foreground text-base font-semibold\">No articles found</h3>\n            <p class=\"text-muted-foreground text-sm\">\n              There are no articles published yet under &ldquo;{{ activeCategory() }}&rdquo;.\n            </p>\n            <button ui-button variant=\"outline\" size=\"sm\" (click)=\"activeCategory.set('All')\">Show all articles</button>\n          </div>\n        }\n\n        <!-- Load More Stories Button -->\n        @if (!showAllPosts() && visiblePosts().length > 0) {\n          <div class=\"flex justify-center pt-2\">\n            <button\n              ui-button\n              variant=\"outline\"\n              size=\"lg\"\n              class=\"gap-2 px-8 font-medium shadow-xs\"\n              [disabled]=\"isLoadingMore()\"\n              (click)=\"handleLoadMore()\"\n            >\n              @if (isLoadingMore()) {\n                <lucide-icon [img]=\"Loader2\" class=\"size-4 animate-spin\" />\n              }\n              <span>{{ isLoadingMore() ? 'Loading articles...' : 'Load More Stories' }}</span>\n            </button>\n          </div>\n        }\n\n        <!-- Newsletter Subscribe Box -->\n        <div ui-card class=\"border-border bg-card/60 relative overflow-hidden shadow-xs\">\n          <div\n            ui-card-content\n            class=\"relative z-10 flex flex-col items-center justify-between gap-8 p-8 sm:p-10 md:flex-row\"\n          >\n            <div class=\"max-w-xl space-y-2 text-center md:text-left\">\n              <div\n                class=\"bg-primary/10 text-primary mx-auto flex size-10 items-center justify-center rounded-lg md:mx-0\"\n              >\n                <lucide-icon [img]=\"Mail\" class=\"size-5\" />\n              </div>\n              <h3 class=\"text-foreground text-2xl font-bold tracking-tight\">Subscribe to our editorial dispatch</h3>\n              <p class=\"text-muted-foreground text-sm leading-relaxed\">\n                Get weekly teardowns on frontend architecture, component design systems, and web performance delivered\n                straight to your inbox.\n              </p>\n            </div>\n\n            <div class=\"w-full max-w-md\">\n              @if (!isSubscribed()) {\n                <form class=\"flex flex-col gap-2 sm:flex-row\" (submit)=\"handleSubscribe($event)\">\n                  <ui-input\n                    [value]=\"emailInput()\"\n                    (valueChange)=\"emailInput.set($event)\"\n                    type=\"email\"\n                    placeholder=\"name@company.com\"\n                    required\n                    aria-label=\"Email address\"\n                    class=\"bg-background h-10 shadow-xs\"\n                  />\n                  <button ui-button type=\"submit\" class=\"shrink-0\">Subscribe</button>\n                </form>\n                <p class=\"text-muted-foreground mt-2 text-center text-xs sm:text-left\">\n                  No spam. Sent bi-weekly. Unsubscribe with one click.\n                </p>\n              } @else {\n                <div\n                  class=\"bg-primary/10 border-primary/20 text-foreground flex items-center gap-3 rounded-lg border p-3.5 text-sm font-medium\"\n                >\n                  <lucide-icon [img]=\"Check\" class=\"text-primary size-5 shrink-0\" />\n                  <span>You&apos;re subscribed! Check your inbox for the welcome issue.</span>\n                </div>\n              }\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiBlogPostCardGridComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly BookOpen = BookOpen\n  protected readonly Check = Check\n  protected readonly Clock = Clock\n  protected readonly Loader2 = Loader2\n  protected readonly Mail = Mail\n  protected readonly Star = Star\n\n  protected readonly categories = categories\n  protected readonly featured = featuredPost\n\n  @Input() showFeatured = true\n  @Input('class') className?: string\n\n  readonly activeCategory = signal<BlogCategory>('All')\n  readonly isLoadingMore = signal(false)\n  readonly showAllPosts = signal(false)\n  readonly emailInput = signal('')\n  readonly isSubscribed = signal(false)\n  private loadTimer: ReturnType<typeof setTimeout> | undefined\n\n  readonly visiblePosts = computed(() => {\n    const pool = this.showAllPosts() ? [...initialPosts, ...additionalPosts] : initialPosts\n    if (this.activeCategory() === 'All') return pool\n    return pool.filter((p) => p.category === this.activeCategory())\n  })\n\n  readonly isHeroVisible = computed(() => {\n    if (!this.showFeatured) return false\n    return this.activeCategory() === 'All' || featuredPost.category === this.activeCategory()\n  })\n\n  get rootClass(): string {\n    return cn('bg-background w-full py-12 sm:py-16 lg:py-20', this.className)\n  }\n\n  handleCategorySelect(cat: BlogCategory): void {\n    this.activeCategory.set(cat)\n  }\n\n  handleLoadMore(): void {\n    this.isLoadingMore.set(true)\n    clearTimeout(this.loadTimer)\n    this.loadTimer = setTimeout(() => {\n      this.showAllPosts.set(true)\n      this.isLoadingMore.set(false)\n    }, 400)\n  }\n\n  handleSubscribe(event: Event): void {\n    event.preventDefault()\n    if (!this.emailInput().includes('@')) return\n    this.isSubscribed.set(true)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/blog-post-card-grid/blog-post-card-grid.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/blog-post-card-grid/index.ts",
      "content": "export {\n  UiBlogPostCardGridComponent,\n  type Author,\n  type BlogCategory,\n  type BlogPost,\n} from './blog-post-card-grid.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/blog-post-card-grid/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/avatar.json",
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/input.json",
    "https://uipkge.dev/r/angular/separator.json"
  ],
  "description": "Modern editorial magazine 3-column article card grid with featured hero story, reading time pills, category filter badges, author avatars, and newsletter subscription box.",
  "categories": [
    "media",
    "marketing",
    "content"
  ]
}