{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "testimonial-social-cards",
  "title": "Testimonial — Social Cards",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/testimonial-social-cards/testimonial-social-cards.component.ts",
      "content": "// Masonry of social-post style endorsements with handle, avatar, timestamp, body copy,\n// and engagement counts — written as posts, not polished quotes. Port of the Vue/React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { Heart, LucideAngularModule, MessageCircle, Repeat2 } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiAvatarComponent, UiAvatarFallbackComponent } 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'\n\nexport interface SocialPost {\n  name: string\n  handle: string\n  initials: string\n  when: string\n  body: string\n  replies: number\n  reposts: number\n  likes: number\n}\n\nexport const socialPosts: SocialPost[] = [\n  {\n    name: 'Erin Walsh',\n    handle: '@erinwalsh',\n    initials: 'EW',\n    when: '4h',\n    body: 'closed the month in four days. four. i have been doing this for eleven years and that number has never started with a four.',\n    replies: 18,\n    reposts: 42,\n    likes: 310,\n  },\n  {\n    name: 'Marcus Ellery',\n    handle: '@mellery',\n    initials: 'ME',\n    when: '1d',\n    body: 'the thing that sold me was the diff. every metric change opens a PR. i can finally review what finance is about to publish instead of finding out in the board deck.',\n    replies: 7,\n    reposts: 91,\n    likes: 604,\n  },\n  {\n    name: 'Anna Reyes',\n    handle: '@annareyes',\n    initials: 'AR',\n    when: '2d',\n    body: 'migration took longer than the marketing site says (three weeks, not one) but nothing broke and we did not copy a single row out of the warehouse.',\n    replies: 24,\n    reposts: 33,\n    likes: 188,\n  },\n  {\n    name: 'Tom Fairbanks',\n    handle: '@tfairbanks',\n    initials: 'TF',\n    when: '3d',\n    body: 'row level scoping wired to okta groups. someone changes teams, their dashboards change with them. this used to be a quarterly cleanup ticket.',\n    replies: 11,\n    reposts: 57,\n    likes: 402,\n  },\n  {\n    name: 'Priya Raman',\n    handle: '@praman',\n    initials: 'PR',\n    when: '5d',\n    body: 'forecast review used to open with twenty minutes of reconciling two decks. now it opens with the forecast. small change, enormous difference.',\n    replies: 5,\n    reposts: 28,\n    likes: 233,\n  },\n  {\n    name: 'Sophie Lindqvist',\n    handle: '@slindqvist',\n    initials: 'SL',\n    when: '1w',\n    body: 'handed the auditors an exported change log instead of a shared folder and they were visibly confused about what to do with their afternoon.',\n    replies: 31,\n    reposts: 120,\n    likes: 870,\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-testimonial-social-cards, [ui-testimonial-social-cards]',\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    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n  ],\n  template: `\n    <section data-slot=\"testimonial-social-cards\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n        <div class=\"max-w-2xl\">\n          <span ui-badge variant=\"secondary\">In the wild</span>\n          <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Posted without being asked</h2>\n          <p class=\"text-muted-foreground mt-3 text-lg\">\n            Unedited, including the one about the migration taking three weeks.\n          </p>\n        </div>\n\n        <!-- CSS columns give a masonry flow with no JS layout pass; cards use\n             break-inside to avoid splitting across a column boundary. -->\n        <div class=\"mt-10 gap-4 sm:columns-2 lg:columns-3\">\n          @for (post of posts; track post.handle) {\n            <div ui-card class=\"mb-4 break-inside-avoid\">\n              <div ui-card-content class=\"p-5\">\n                <div class=\"flex items-center gap-3\">\n                  <ui-avatar class=\"size-9\">\n                    <ui-avatar-fallback class=\"text-xs\">{{ post.initials }}</ui-avatar-fallback>\n                  </ui-avatar>\n                  <div class=\"min-w-0\">\n                    <p class=\"truncate text-sm font-medium\">{{ post.name }}</p>\n                    <p class=\"text-muted-foreground truncate text-xs\">{{ post.handle }} · {{ post.when }}</p>\n                  </div>\n                </div>\n\n                <p class=\"mt-3 text-sm leading-relaxed\">{{ post.body }}</p>\n\n                <div class=\"text-muted-foreground mt-4 flex items-center gap-5 text-xs\">\n                  <button ui-button variant=\"ghost\" size=\"sm\" class=\"h-auto gap-1.5 px-1.5 py-1 text-xs font-normal\">\n                    <lucide-icon [img]=\"MessageCircle\" class=\"size-3.5\" aria-hidden=\"true\" />\n                    {{ post.replies }}\n                  </button>\n                  <button ui-button variant=\"ghost\" size=\"sm\" class=\"h-auto gap-1.5 px-1.5 py-1 text-xs font-normal\">\n                    <lucide-icon [img]=\"Repeat2\" class=\"size-3.5\" aria-hidden=\"true\" />\n                    {{ post.reposts }}\n                  </button>\n                  <button ui-button variant=\"ghost\" size=\"sm\" class=\"h-auto gap-1.5 px-1.5 py-1 text-xs font-normal\">\n                    <lucide-icon [img]=\"Heart\" class=\"size-3.5\" aria-hidden=\"true\" />\n                    {{ post.likes }}\n                  </button>\n                </div>\n              </div>\n            </div>\n          }\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiTestimonialSocialCardsComponent {\n  protected readonly Heart = Heart\n  protected readonly MessageCircle = MessageCircle\n  protected readonly Repeat2 = Repeat2\n\n  protected readonly posts = socialPosts\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/testimonial-social-cards/testimonial-social-cards.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/testimonial-social-cards/index.ts",
      "content": "export { UiTestimonialSocialCardsComponent, type SocialPost, socialPosts } from './testimonial-social-cards.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/testimonial-social-cards/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"
  ],
  "description": "Masonry of social-post style endorsements with handle, avatar, timestamp, body copy, and engagement counts, formatted as posts rather than polished marketing quotes.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "testimonial"
}