{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "invoices-list",
  "title": "Invoices List",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/invoices-list/invoices-list.component.ts",
      "content": "import { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { Check, Download, Eye, LucideAngularModule, MoreHorizontal, Plus } 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'\nimport {\n  UiDropdownMenuComponent,\n  UiDropdownMenuContentComponent,\n  UiDropdownMenuItemComponent,\n  UiDropdownMenuSeparatorComponent,\n  UiDropdownMenuTriggerComponent,\n} from '@/ui/dropdown-menu/dropdown-menu.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport type InvoiceStatus = 'paid' | 'pending' | 'overdue' | 'draft'\n\nexport interface Invoice {\n  id: string\n  number: string\n  client: string\n  issued: string\n  due: string\n  amount: string\n  status: InvoiceStatus\n}\n\nconst summary = [\n  { label: 'Total outstanding', value: '$12,480.00', note: '5 unpaid invoices', tone: '' },\n  { label: 'Paid this month', value: '$28,930.00', note: '+12% vs last month', tone: '' },\n  { label: 'Overdue', value: '$3,120.00', note: '2 invoices past due', tone: 'text-destructive' },\n]\n\nconst statusClass: Record<InvoiceStatus, string> = {\n  paid: 'bg-success/10 text-success',\n  pending: 'bg-warning/10 text-warning',\n  overdue: 'bg-destructive/10 text-destructive',\n  draft: '',\n}\n\nconst invoices: Invoice[] = [\n  {\n    id: 'i1',\n    number: 'INV-2026-0142',\n    client: 'Acme Corp',\n    issued: 'Aug 18, 2026',\n    due: 'Sep 1, 2026',\n    amount: '$4,800.00',\n    status: 'pending',\n  },\n  {\n    id: 'i2',\n    number: 'INV-2026-0141',\n    client: 'Northwind Traders',\n    issued: 'Aug 15, 2026',\n    due: 'Aug 30, 2026',\n    amount: '$2,350.00',\n    status: 'overdue',\n  },\n  {\n    id: 'i3',\n    number: 'INV-2026-0140',\n    client: 'Globex Industries',\n    issued: 'Aug 12, 2026',\n    due: 'Sep 10, 2026',\n    amount: '$1,200.00',\n    status: 'draft',\n  },\n  {\n    id: 'i4',\n    number: 'INV-2026-0139',\n    client: 'Helios Labs',\n    issued: 'Aug 8, 2026',\n    due: 'Aug 22, 2026',\n    amount: '$6,750.00',\n    status: 'paid',\n  },\n  {\n    id: 'i5',\n    number: 'INV-2026-0138',\n    client: 'Acme Corp',\n    issued: 'Aug 5, 2026',\n    due: 'Aug 19, 2026',\n    amount: '$770.00',\n    status: 'paid',\n  },\n  {\n    id: 'i6',\n    number: 'INV-2026-0137',\n    client: 'Vertex Media',\n    issued: 'Jul 30, 2026',\n    due: 'Aug 13, 2026',\n    amount: '$3,120.00',\n    status: 'overdue',\n  },\n  {\n    id: 'i7',\n    number: 'INV-2026-0136',\n    client: 'Initech Systems',\n    issued: 'Jul 24, 2026',\n    due: 'Aug 7, 2026',\n    amount: '$5,400.00',\n    status: 'paid',\n  },\n]\n\n/**\n * InvoicesList -- the React block, 1:1: header with a New invoice action, a three-card\n * summary strip (total outstanding, paid this month, overdue), and an invoice table pairing\n * monospace invoice numbers with avatar clients, issue/due dates, tabular-nums amounts,\n * color-coded status badges, and a per-row View/Download/Mark-as-paid dropdown, closed by\n * a pagination hint. Data is stubbed inline; swap for your source.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-invoices-list, [ui-invoices-list]',\n  standalone: true,\n  // React renders the root <div> 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    UiDropdownMenuComponent,\n    UiDropdownMenuContentComponent,\n    UiDropdownMenuItemComponent,\n    UiDropdownMenuSeparatorComponent,\n    UiDropdownMenuTriggerComponent,\n    UiTableComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <div data-slot=\"invoices-list\" [class]=\"rootClass\">\n      <div class=\"flex flex-wrap items-center justify-between gap-4\">\n        <div>\n          <h2 class=\"text-2xl font-bold tracking-tight\">Invoices</h2>\n          <p class=\"text-muted-foreground mt-1 text-sm\">Manage billing for all of your clients.</p>\n        </div>\n        <button ui-button>\n          <lucide-icon [img]=\"Plus\" />\n          New invoice\n        </button>\n      </div>\n\n      <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n        @for (item of summary; track item.label) {\n          <div ui-card class=\"shadow-xs\">\n            <div ui-card-content class=\"space-y-1\">\n              <p class=\"text-muted-foreground text-sm\">{{ item.label }}</p>\n              <p class=\"text-2xl font-bold tracking-tight tabular-nums\" [class]=\"item.tone\">{{ item.value }}</p>\n              <p class=\"text-muted-foreground text-xs\">{{ item.note }}</p>\n            </div>\n          </div>\n        }\n      </div>\n\n      <div class=\"bg-card overflow-x-auto rounded-lg border shadow-xs\">\n        <table ui-table>\n          <thead ui-table-header>\n            <tr ui-table-row>\n              <th ui-table-head>Invoice</th>\n              <th ui-table-head>Client</th>\n              <th ui-table-head>Issued</th>\n              <th ui-table-head>Due</th>\n              <th ui-table-head class=\"text-right\">Amount</th>\n              <th ui-table-head>Status</th>\n              <th ui-table-head class=\"w-12\"><span class=\"sr-only\">Actions</span></th>\n            </tr>\n          </thead>\n          <tbody ui-table-body>\n            @for (invoice of invoices; track invoice.id) {\n              <tr ui-table-row>\n                <td ui-table-cell class=\"font-mono text-xs font-medium\">{{ invoice.number }}</td>\n                <td ui-table-cell>\n                  <div class=\"flex items-center gap-2\">\n                    <ui-avatar class=\"size-7\">\n                      <ui-avatar-fallback class=\"text-xs\">{{ initials(invoice.client) }}</ui-avatar-fallback>\n                    </ui-avatar>\n                    <span class=\"truncate text-sm font-medium\">{{ invoice.client }}</span>\n                  </div>\n                </td>\n                <td ui-table-cell class=\"text-muted-foreground text-sm\">{{ invoice.issued }}</td>\n                <td ui-table-cell class=\"text-muted-foreground text-sm\">{{ invoice.due }}</td>\n                <td ui-table-cell class=\"text-right font-medium tabular-nums\">{{ invoice.amount }}</td>\n                <td ui-table-cell>\n                  <span\n                    ui-badge\n                    [variant]=\"invoice.status === 'draft' ? 'secondary' : 'default'\"\n                    [class]=\"badgeClass(invoice.status)\"\n                  >\n                    {{ invoice.status }}\n                  </span>\n                </td>\n                <td ui-table-cell>\n                  <ui-dropdown-menu>\n                    <button\n                      ui-button\n                      ui-dropdown-menu-trigger\n                      variant=\"ghost\"\n                      size=\"icon-sm\"\n                      class=\"text-muted-foreground\"\n                    >\n                      <lucide-icon [img]=\"MoreHorizontal\" />\n                      <span class=\"sr-only\">Open actions for {{ invoice.number }}</span>\n                    </button>\n                    <ui-dropdown-menu-content align=\"end\">\n                      <ui-dropdown-menu-item>\n                        <lucide-icon [img]=\"Eye\" />\n                        <span>View</span>\n                      </ui-dropdown-menu-item>\n                      <ui-dropdown-menu-item>\n                        <lucide-icon [img]=\"Download\" />\n                        <span>Download</span>\n                      </ui-dropdown-menu-item>\n                      <ui-dropdown-menu-separator />\n                      <ui-dropdown-menu-item [disabled]=\"invoice.status === 'paid' || invoice.status === 'draft'\">\n                        <lucide-icon [img]=\"Check\" />\n                        <span>Mark as paid</span>\n                      </ui-dropdown-menu-item>\n                    </ui-dropdown-menu-content>\n                  </ui-dropdown-menu>\n                </td>\n              </tr>\n            }\n          </tbody>\n        </table>\n      </div>\n\n      <div class=\"flex items-center justify-between\">\n        <p class=\"text-muted-foreground text-sm\">Showing {{ invoices.length }} of 42 invoices</p>\n        <div class=\"flex items-center gap-2\">\n          <button ui-button variant=\"outline\" size=\"sm\" disabled>Previous</button>\n          <button ui-button variant=\"outline\" size=\"sm\">Next</button>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiInvoicesListComponent {\n  protected readonly Check = Check\n  protected readonly Download = Download\n  protected readonly Eye = Eye\n  protected readonly MoreHorizontal = MoreHorizontal\n  protected readonly Plus = Plus\n\n  protected readonly summary = summary\n  protected readonly invoices = invoices\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('w-full space-y-6', this.className)\n  }\n\n  badgeClass(status: InvoiceStatus): string {\n    return cn('capitalize', statusClass[status])\n  }\n\n  initials(name: string): string {\n    return name\n      .split(' ')\n      .map((part) => part[0])\n      .slice(0, 2)\n      .join('')\n      .toUpperCase()\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/invoices-list/invoices-list.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/invoices-list/index.ts",
      "content": "export { UiInvoicesListComponent, type Invoice, type InvoiceStatus } from './invoices-list.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/invoices-list/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/dropdown-menu.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Invoice history page: header with a New invoice action, a three-card summary strip (total outstanding, paid this month, overdue), and an invoice table pairing monospace invoice numbers with avatar clients, issue/due dates, tabular-nums amounts, color-coded status badges, and a per-row View/Download/Mark-as-paid dropdown, closed by a pagination hint. Data is stubbed inline; swap for your source.",
  "categories": [
    "finance",
    "app",
    "billing"
  ]
}