{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "payroll-run-summary",
  "title": "Payroll Run Summary",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/payroll-run-summary/payroll-run-summary.component.ts",
      "content": "import { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport {\n  Building2,\n  Calendar,\n  CheckCircle2,\n  Clock,\n  CreditCard,\n  DollarSign,\n  Download,\n  Landmark,\n  LucideAngularModule,\n  Receipt,\n  Send,\n  ShieldCheck,\n} 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 {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport interface EmployeeRecord {\n  id: string\n  name: string\n  role: string\n  department: string\n  payType: 'Salary' | 'Hourly'\n  hours: string\n  grossPay: string\n  deductions: string\n  deductionsDetail: string\n  netPay: string\n  paymentMethod: string\n  bankDetail: string\n}\n\ninterface TimelineStep {\n  step: number\n  title: string\n  date: string\n  time: string\n  description: string\n  status: string\n  statusClass: string\n  icon: unknown\n  footer: string\n}\n\ninterface SummaryCard {\n  label: string\n  value: string\n  badge: string\n  description: string\n}\n\nconst timelineSteps: TimelineStep[] = [\n  {\n    step: 1,\n    title: 'ACH Debit Date',\n    date: 'Wednesday, Aug 19, 2026',\n    time: '5:00 PM EST',\n    description: 'Company Operating Account (•••• 9021) debited for payroll & tax liability.',\n    status: 'Completed',\n    statusClass: 'bg-success/10 text-success border-success/20',\n    icon: CheckCircle2,\n    footer: 'Verified',\n  },\n  {\n    step: 2,\n    title: 'Bank Processing',\n    date: 'Thursday, Aug 20, 2026',\n    time: 'Automated Clearing',\n    description: 'Federal Reserve NACHA batch transmission, ACH clearing, and tax escrow lock.',\n    status: 'In Transit',\n    statusClass: 'bg-info/10 text-info border-info/20',\n    icon: Landmark,\n    footer: 'Processing',\n  },\n  {\n    step: 3,\n    title: 'Employee Payday',\n    date: 'Friday, Aug 21, 2026',\n    time: '12:01 AM Local',\n    description: 'Net funds settled across 42 employee accounts and electronic paystubs released.',\n    status: 'Target Payday',\n    statusClass: 'bg-success/10 text-success border-success/20',\n    icon: DollarSign,\n    footer: 'Scheduled',\n  },\n]\n\nconst summaryCards: SummaryCard[] = [\n  {\n    label: 'Total Company Cost',\n    value: '$184,250.00',\n    badge: 'Cycle #16',\n    description: 'Gross pay ($169,670.00) + Employer taxes ($14,580.00)',\n  },\n  {\n    label: 'Net Direct Deposit Pay',\n    value: '$138,420.00',\n    badge: '42 Employees',\n    description: 'Disbursed to 42 employees via automated 100% direct deposit',\n  },\n  {\n    label: 'Employee Withholdings',\n    value: '$31,250.00',\n    badge: 'Federal & State Tax',\n    description: '$31,250.00 · Federal & State Tax, FICA & benefit deductions',\n  },\n  {\n    label: 'Employer Payroll Taxes',\n    value: '$14,580.00',\n    badge: 'FICA & FUTA',\n    description: '$14,580.00 · FICA & FUTA, SUTA employer contributions',\n  },\n]\n\nconst employees: EmployeeRecord[] = [\n  {\n    id: 'emp-1',\n    name: 'Elena Rostova',\n    role: 'Principal Engineer',\n    department: 'Engineering',\n    payType: 'Salary',\n    hours: '80.0 hrs',\n    grossPay: '$8,750.00',\n    deductions: '-$2,140.00',\n    deductionsDetail: 'Pre-tax 401k & Health',\n    netPay: '$6,610.00',\n    paymentMethod: 'Direct Deposit',\n    bankDetail: 'Chase •••• 4892',\n  },\n  {\n    id: 'emp-2',\n    name: 'Marcus Vance',\n    role: 'Staff Architect',\n    department: 'Engineering',\n    payType: 'Salary',\n    hours: '80.0 hrs',\n    grossPay: '$8,125.00',\n    deductions: '-$1,980.00',\n    deductionsDetail: 'Pre-tax 401k & HSA',\n    netPay: '$6,145.00',\n    paymentMethod: 'Direct Deposit',\n    bankDetail: 'Wells Fargo •••• 3109',\n  },\n  {\n    id: 'emp-3',\n    name: 'David Chen',\n    role: 'Senior Full-Stack',\n    department: 'Engineering',\n    payType: 'Salary',\n    hours: '80.0 hrs',\n    grossPay: '$6,875.00',\n    deductions: '-$1,650.00',\n    deductionsDetail: 'Pre-tax 401k & Dental',\n    netPay: '$5,225.00',\n    paymentMethod: 'Direct Deposit',\n    bankDetail: 'Bank of America •••• 7741',\n  },\n  {\n    id: 'emp-4',\n    name: 'Sarah Jenkins',\n    role: 'Frontend Specialist',\n    department: 'Engineering',\n    payType: 'Hourly',\n    hours: '80.0 hrs',\n    grossPay: '$5,492.50',\n    deductions: '-$1,280.00',\n    deductionsDetail: 'Medical & Vision',\n    netPay: '$4,212.50',\n    paymentMethod: 'Direct Deposit',\n    bankDetail: 'Citibank •••• 9018',\n  },\n  {\n    id: 'emp-5',\n    name: 'Alex Rivera',\n    role: 'Product Designer',\n    department: 'Design',\n    payType: 'Salary',\n    hours: '80.0 hrs',\n    grossPay: '$6,250.00',\n    deductions: '-$1,490.00',\n    deductionsDetail: 'Pre-tax 401k & Health',\n    netPay: '$4,760.00',\n    paymentMethod: 'Direct Deposit',\n    bankDetail: 'SVB •••• 6523',\n  },\n]\n\nfunction 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/**\n * PayrollRunSummary -- the React block, 1:1: cycle header with approval badge and submit\n * controls, four payroll metric cards, a direct-deposit ACH funding timeline, and an\n * itemized employee compensation table with avatar, pay-type badge, deductions and net pay.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-payroll-run-summary, [ui-payroll-run-summary]',\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    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiTableComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <div data-slot=\"payroll-run-summary\" [class]=\"rootClass\">\n      <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div class=\"space-y-1.5\">\n          <div class=\"flex flex-wrap items-center gap-3\">\n            <h2 class=\"text-foreground text-2xl font-bold tracking-tight\">Payroll Run Summary</h2>\n            <span\n              ui-badge\n              wrap\n              variant=\"outline\"\n              class=\"border-success/20 bg-success/10 text-success gap-1.5 font-medium\"\n            >\n              <span class=\"bg-success size-1.5 rounded-full\" aria-hidden=\"true\"></span>\n              Approved & Ready to Submit\n            </span>\n          </div>\n          <p class=\"text-muted-foreground flex flex-wrap items-center gap-2 text-sm\">\n            <span class=\"inline-flex items-center gap-1.5\">\n              <lucide-icon [img]=\"Calendar\" class=\"size-4\" />\n              Pay Period: <strong class=\"text-foreground font-medium\">Aug 01, 2026 – Aug 15, 2026</strong>\n            </span>\n            <span> Pay Date: <strong class=\"text-foreground font-medium\">Aug 21</strong> </span>\n          </p>\n        </div>\n\n        <div class=\"flex flex-wrap items-center gap-2.5\">\n          <button ui-button aria-label=\"Download attachment\" variant=\"outline\">\n            <lucide-icon [img]=\"Download\" class=\"size-4\" />\n            Export Payroll CSV\n          </button>\n          <button ui-button>\n            <lucide-icon [img]=\"Send\" class=\"size-4\" />\n            Submit Payroll ($184,250.00)\n          </button>\n        </div>\n      </div>\n\n      <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        @for (card of summaryCards; track card.label) {\n          <div ui-card class=\"relative overflow-hidden shadow-xs\">\n            <div ui-card-header class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n              <h3 ui-card-title class=\"text-muted-foreground text-sm font-medium\">{{ card.label }}</h3>\n              <span ui-badge wrap variant=\"secondary\" class=\"text-xs font-normal\">{{ card.badge }}</span>\n            </div>\n            <div ui-card-content class=\"space-y-1\">\n              <div class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">{{ card.value }}</div>\n              <p class=\"text-muted-foreground text-xs leading-relaxed\">{{ card.description }}</p>\n            </div>\n          </div>\n        }\n      </div>\n\n      <div ui-card class=\"border-border shadow-xs\">\n        <div ui-card-header class=\"border-b pb-3\">\n          <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n            <div class=\"flex items-center gap-2\">\n              <lucide-icon [img]=\"Clock\" class=\"text-muted-foreground size-4\" />\n              <h3 ui-card-title class=\"text-sm font-semibold tracking-tight\">Direct Deposit Funding Timeline</h3>\n            </div>\n            <span ui-badge wrap variant=\"outline\" class=\"text-muted-foreground w-fit text-xs font-normal\">\n              ACH 2-Day Settlement Window\n            </span>\n          </div>\n        </div>\n        <div ui-card-content class=\"pt-4\">\n          <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n            @for (item of timelineSteps; track item.step; let idx = $index) {\n              <div class=\"bg-card relative flex flex-col justify-between rounded-lg border p-4 shadow-xs\">\n                <div class=\"space-y-2\">\n                  <div class=\"flex flex-wrap items-center justify-between gap-2\">\n                    <div class=\"flex min-w-0 items-center gap-2\">\n                      <div\n                        class=\"bg-muted text-foreground flex size-7 items-center justify-center rounded-full text-xs font-semibold\"\n                      >\n                        {{ item.step }}\n                      </div>\n                      <span class=\"text-foreground text-xs font-semibold tracking-tight\">{{ item.title }}</span>\n                    </div>\n                    <span ui-badge [class]=\"timelineStatusClass(item)\">{{ item.status }}</span>\n                  </div>\n                  <div class=\"pt-1\">\n                    <p class=\"text-foreground text-xs font-medium\">{{ item.date }}</p>\n                    <p class=\"text-muted-foreground text-xs\">{{ item.time }}</p>\n                  </div>\n                  <p class=\"text-muted-foreground text-xs leading-relaxed\">{{ item.description }}</p>\n                </div>\n                <div class=\"text-muted-foreground mt-3 flex items-center justify-between border-t pt-2 text-xs\">\n                  <span class=\"inline-flex items-center gap-1 font-medium\">\n                    <lucide-icon [img]=\"asIcon(item.icon)\" class=\"text-foreground/70 size-3.5\" />\n                    {{ item.footer }}\n                  </span>\n                  @if (idx < timelineSteps.length - 1) {\n                    <span class=\"text-muted-foreground/50 hidden md:inline-flex\">Next: Step {{ idx + 2 }}</span>\n                  }\n                </div>\n              </div>\n            }\n          </div>\n        </div>\n      </div>\n\n      <div class=\"bg-card overflow-hidden rounded-lg border shadow-xs\">\n        <div class=\"flex flex-col gap-2 border-b p-4 sm:flex-row sm:items-center sm:justify-between\">\n          <div>\n            <h3 class=\"text-foreground text-base font-semibold tracking-tight\">Employee Compensation Breakdown</h3>\n            <p class=\"text-muted-foreground mt-0.5 text-xs\">\n              5 of 42 employees shown in active batch · 80.0 standard cycle base hours\n            </p>\n          </div>\n          <div class=\"flex items-center gap-2\">\n            <span ui-badge wrap variant=\"secondary\" class=\"text-xs font-medium\">42 Total Employees</span>\n            <span ui-badge wrap variant=\"outline\" class=\"border-success/20 text-success text-xs font-medium\">\n              Approved & Ready to Submit\n            </span>\n          </div>\n        </div>\n\n        <div class=\"overflow-x-auto\">\n          <table ui-table>\n            <thead ui-table-header>\n              <tr ui-table-row class=\"bg-muted/40 hover:bg-muted/40\">\n                <th ui-table-head class=\"min-w-[220px]\">Employee</th>\n                <th ui-table-head>Pay Type</th>\n                <th ui-table-head class=\"text-right\">Hours</th>\n                <th ui-table-head class=\"text-right\">Gross Pay</th>\n                <th ui-table-head class=\"min-w-[180px] text-right\">Total Deductions</th>\n                <th ui-table-head class=\"text-right\">Net Pay</th>\n                <th ui-table-head class=\"min-w-[220px]\">Payment Method</th>\n              </tr>\n            </thead>\n            <tbody ui-table-body>\n              @for (emp of employees; track emp.id) {\n                <tr ui-table-row class=\"hover:bg-muted/30\">\n                  <td ui-table-cell>\n                    <div class=\"flex items-center gap-3\">\n                      <ui-avatar class=\"size-8 border\">\n                        <ui-avatar-fallback class=\"text-xs font-medium\">{{ initials(emp.name) }}</ui-avatar-fallback>\n                      </ui-avatar>\n                      <div class=\"flex min-w-0 flex-col\">\n                        <div class=\"flex items-center gap-2\">\n                          <span class=\"text-foreground truncate text-sm font-semibold\">{{ emp.name }}</span>\n                          <span ui-badge wrap variant=\"outline\" class=\"px-1.5 py-0 text-xs font-normal\">\n                            {{ emp.department }}\n                          </span>\n                        </div>\n                        <span class=\"text-muted-foreground truncate text-xs\">{{ emp.role }}</span>\n                      </div>\n                    </div>\n                  </td>\n                  <td ui-table-cell>\n                    <span\n                      ui-badge\n                      wrap\n                      [variant]=\"emp.payType === 'Salary' ? 'outline' : 'secondary'\"\n                      class=\"text-xs font-medium\"\n                    >\n                      {{ emp.payType }}\n                    </span>\n                  </td>\n                  <td ui-table-cell class=\"text-foreground text-right font-mono text-xs tabular-nums\">\n                    {{ emp.hours }}\n                  </td>\n                  <td ui-table-cell class=\"text-foreground text-right font-medium tabular-nums\">{{ emp.grossPay }}</td>\n                  <td ui-table-cell class=\"text-right\">\n                    <div class=\"flex flex-col items-end\">\n                      <span class=\"text-destructive text-sm font-medium tabular-nums\">{{ emp.deductions }}</span>\n                      <span class=\"text-muted-foreground text-xs\">{{ emp.deductionsDetail }}</span>\n                    </div>\n                  </td>\n                  <td ui-table-cell class=\"text-right\">\n                    <span class=\"text-success text-sm font-bold tabular-nums\">{{ emp.netPay }}</span>\n                  </td>\n                  <td ui-table-cell>\n                    <div class=\"flex items-center gap-2\">\n                      <lucide-icon [img]=\"Landmark\" class=\"text-muted-foreground size-4 shrink-0\" />\n                      <div class=\"flex min-w-0 flex-col\">\n                        <span class=\"text-foreground truncate text-xs font-medium\">{{ emp.paymentMethod }}</span>\n                        <span class=\"text-muted-foreground truncate text-xs\">{{ emp.bankDetail }}</span>\n                      </div>\n                    </div>\n                  </td>\n                </tr>\n              }\n            </tbody>\n          </table>\n        </div>\n\n        <div class=\"bg-muted/20 flex flex-col items-center justify-between gap-3 border-t p-4 sm:flex-row\">\n          <p class=\"text-muted-foreground text-xs\">\n            Showing 5 of 42 employees · Reconciliation verified against IRS Form 941 schedules\n          </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      <div class=\"hidden items-center gap-2\">\n        <lucide-icon [img]=\"Building2\" />\n        <lucide-icon [img]=\"CreditCard\" />\n        <lucide-icon [img]=\"Receipt\" />\n        <lucide-icon [img]=\"ShieldCheck\" />\n      </div>\n    </div>\n  `,\n})\nexport class UiPayrollRunSummaryComponent {\n  protected readonly Calendar = Calendar\n  protected readonly Clock = Clock\n  protected readonly Download = Download\n  protected readonly Landmark = Landmark\n  protected readonly Send = Send\n  protected readonly Building2 = Building2\n  protected readonly CreditCard = CreditCard\n  protected readonly Receipt = Receipt\n  protected readonly ShieldCheck = ShieldCheck\n\n  @Input('class') className?: string\n\n  protected readonly summaryCards = summaryCards\n  protected readonly timelineSteps = timelineSteps\n  protected readonly employees = employees\n\n  get rootClass(): string {\n    return cn('w-full space-y-6', this.className)\n  }\n\n  initials(name: string): string {\n    return initials(name)\n  }\n\n  asIcon(icon: unknown): never {\n    return icon as never\n  }\n\n  timelineStatusClass(item: TimelineStep): string {\n    return cn('text-xs font-medium capitalize', item.statusClass)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/payroll-run-summary/payroll-run-summary.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/payroll-run-summary/index.ts",
      "content": "export { UiPayrollRunSummaryComponent, type EmployeeRecord } from './payroll-run-summary.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/payroll-run-summary/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/table.json"
  ],
  "description": "Gusto/Rippling style bi-weekly company payroll execution preview and tax reconciliation: cycle header with approval badge and submission controls, 4 primary payroll metric cards (company cost, net pay, employee withholdings, employer taxes), direct deposit ACH funding timeline, and itemized employee payroll table.",
  "categories": [
    "finance",
    "app",
    "billing"
  ]
}