{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "transaction-feed",
  "title": "Transaction Feed",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/transaction-feed/TransactionFeed.vue",
      "content": "<script setup lang=\"ts\">\nimport type { Component, HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport {\n  Building2,\n  Car,\n  Clock,\n  Cloud,\n  CreditCard,\n  Download,\n  Eye,\n  FileCheck,\n  GitBranch,\n  Mail,\n  MessageSquare,\n  MoreHorizontal,\n  Palette,\n  Paperclip,\n  Plane,\n  Plus,\n  Receipt,\n  RotateCcw,\n  Search,\n  ShieldAlert,\n  TrendingUp,\n  Upload,\n  Utensils,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent } from '@/components/ui/card'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport type TransactionStatus = 'cleared' | 'pending' | 'receipt_needed'\nexport type CategoryKey = 'cloud' | 'travel' | 'saas' | 'transport' | 'office' | 'meals'\n\nexport interface Cardholder {\n  name: string\n  avatar: string\n  initials: string\n  cardLast4: string\n  cardType: 'Virtual' | 'Physical'\n}\n\nexport interface Transaction {\n  id: string\n  merchant: string\n  merchantNote: string\n  merchantIcon: Component\n  category: string\n  categoryKey: CategoryKey\n  cardholder: Cardholder\n  date: string\n  status: TransactionStatus\n  statusLabel: string\n  amount: string\n  isRefund: boolean\n  hasReceipt: boolean\n  receiptFileName?: string\n}\n\nconst props = defineProps<{\n  class?: HTMLAttributes['class']\n}>()\n\nconst search = ref('')\nconst categoryFilter = ref('all')\nconst dateRangeFilter = ref('this_month')\nconst statusFilter = ref('all')\n\nconst categoryStyles: Record<CategoryKey, string> = {\n  cloud: 'bg-info/10 text-info border-info/20',\n  travel: 'bg-chart-1/10 text-chart-1 border-chart-1/20',\n  saas: 'bg-chart-2/10 text-chart-2 border-chart-2/20',\n  transport: 'bg-warning/10 text-warning border-warning/20',\n  office: 'bg-chart-3/10 text-chart-3 border-chart-3/20',\n  meals: 'bg-success/10 text-success border-success/20',\n}\n\nconst statusStyles: Record<TransactionStatus, string> = {\n  cleared: 'bg-success/10 text-success border-success/20',\n  pending: 'bg-info/10 text-info border-info/20',\n  receipt_needed: 'bg-warning/10 text-warning border-warning/20',\n}\n\nconst statusDots: Record<TransactionStatus, string> = {\n  cleared: 'bg-success',\n  pending: 'bg-info',\n  receipt_needed: 'bg-warning',\n}\n\nconst transactions: Transaction[] = [\n  {\n    id: 'tx-01',\n    merchant: 'AWS Cloud Services',\n    merchantNote: 'Production us-east-1 compute & S3',\n    merchantIcon: Cloud,\n    category: 'Cloud Hosting',\n    categoryKey: 'cloud',\n    cardholder: {\n      name: 'Elena Rostova',\n      avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',\n      initials: 'ER',\n      cardLast4: '4892',\n      cardType: 'Virtual',\n    },\n    date: 'Aug 21, 2026 · 14:28',\n    status: 'cleared',\n    statusLabel: 'Cleared',\n    amount: '-$1,420.00',\n    isRefund: false,\n    hasReceipt: true,\n    receiptFileName: 'aws-invoice-aug-2026.pdf',\n  },\n  {\n    id: 'tx-02',\n    merchant: 'Delta Air Lines',\n    merchantNote: 'SFO → JFK nonstop (Q3 Conf)',\n    merchantIcon: Plane,\n    category: 'Travel',\n    categoryKey: 'travel',\n    cardholder: {\n      name: 'Marcus Chen',\n      avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&auto=format&fit=crop&q=80',\n      initials: 'MC',\n      cardLast4: '3190',\n      cardType: 'Physical',\n    },\n    date: 'Aug 21, 2026 · 11:15',\n    status: 'pending',\n    statusLabel: 'Pending',\n    amount: '-$849.00',\n    isRefund: false,\n    hasReceipt: true,\n    receiptFileName: 'delta-eticket-dl8932.pdf',\n  },\n  {\n    id: 'tx-03',\n    merchant: 'GitHub Enterprise',\n    merchantNote: '42 Enterprise team seats',\n    merchantIcon: GitBranch,\n    category: 'SaaS',\n    categoryKey: 'saas',\n    cardholder: {\n      name: 'Amara Okafor',\n      avatar: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=100&auto=format&fit=crop&q=80',\n      initials: 'AO',\n      cardLast4: '9455',\n      cardType: 'Virtual',\n    },\n    date: 'Aug 20, 2026 · 09:00',\n    status: 'cleared',\n    statusLabel: 'Cleared',\n    amount: '-$882.00',\n    isRefund: false,\n    hasReceipt: true,\n    receiptFileName: 'github-inv-aug2026.pdf',\n  },\n  {\n    id: 'tx-04',\n    merchant: 'Uber for Business',\n    merchantNote: 'Client dinner return ride',\n    merchantIcon: Car,\n    category: 'Transport',\n    categoryKey: 'transport',\n    cardholder: {\n      name: 'Sarah Jenkins',\n      avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&auto=format&fit=crop&q=80',\n      initials: 'SJ',\n      cardLast4: '6021',\n      cardType: 'Physical',\n    },\n    date: 'Aug 19, 2026 · 22:45',\n    status: 'receipt_needed',\n    statusLabel: 'Receipt Needed',\n    amount: '-$48.50',\n    isRefund: false,\n    hasReceipt: false,\n  },\n  {\n    id: 'tx-05',\n    merchant: 'Figma Professional',\n    merchantNote: 'Design team organization plan',\n    merchantIcon: Palette,\n    category: 'SaaS',\n    categoryKey: 'saas',\n    cardholder: {\n      name: 'Priya Nair',\n      avatar: 'https://images.unsplash.com/photo-1580489944761-15a19d654956?w=100&auto=format&fit=crop&q=80',\n      initials: 'PN',\n      cardLast4: '7712',\n      cardType: 'Virtual',\n    },\n    date: 'Aug 19, 2026 · 16:30',\n    status: 'cleared',\n    statusLabel: 'Cleared',\n    amount: '-$360.00',\n    isRefund: false,\n    hasReceipt: true,\n    receiptFileName: 'figma-subscription-receipt.pdf',\n  },\n  {\n    id: 'tx-06',\n    merchant: 'WeWork Coworking',\n    merchantNote: 'NYC satellite team hot desks',\n    merchantIcon: Building2,\n    category: 'Office',\n    categoryKey: 'office',\n    cardholder: {\n      name: 'Jonas Weber',\n      avatar: 'https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?w=100&auto=format&fit=crop&q=80',\n      initials: 'JW',\n      cardLast4: '1109',\n      cardType: 'Physical',\n    },\n    date: 'Aug 18, 2026 · 10:00',\n    status: 'receipt_needed',\n    statusLabel: 'Receipt Needed',\n    amount: '-$1,250.00',\n    isRefund: false,\n    hasReceipt: false,\n  },\n  {\n    id: 'tx-07',\n    merchant: 'Google Workspace',\n    merchantNote: 'Security & suite - 55 users',\n    merchantIcon: Mail,\n    category: 'SaaS',\n    categoryKey: 'saas',\n    cardholder: {\n      name: 'Elena Rostova',\n      avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',\n      initials: 'ER',\n      cardLast4: '4892',\n      cardType: 'Virtual',\n    },\n    date: 'Aug 17, 2026 · 08:30',\n    status: 'cleared',\n    statusLabel: 'Cleared',\n    amount: '-$660.00',\n    isRefund: false,\n    hasReceipt: true,\n    receiptFileName: 'google-workspace-statement.pdf',\n  },\n  {\n    id: 'tx-08',\n    merchant: 'Slack Pro',\n    merchantNote: 'Vendor annual prepay refund adjustment',\n    merchantIcon: MessageSquare,\n    category: 'SaaS',\n    categoryKey: 'saas',\n    cardholder: {\n      name: 'Amara Okafor',\n      avatar: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=100&auto=format&fit=crop&q=80',\n      initials: 'AO',\n      cardLast4: '9455',\n      cardType: 'Virtual',\n    },\n    date: 'Aug 16, 2026 · 15:40',\n    status: 'cleared',\n    statusLabel: 'Cleared',\n    amount: '+$5,000.00',\n    isRefund: true,\n    hasReceipt: true,\n    receiptFileName: 'slack-credit-adjustment.pdf',\n  },\n  {\n    id: 'tx-09',\n    merchant: 'Sweetgreen Catering',\n    merchantNote: 'Quarterly all-hands team lunch',\n    merchantIcon: Utensils,\n    category: 'Meals',\n    categoryKey: 'meals',\n    cardholder: {\n      name: 'Marcus Chen',\n      avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&auto=format&fit=crop&q=80',\n      initials: 'MC',\n      cardLast4: '3190',\n      cardType: 'Physical',\n    },\n    date: 'Aug 15, 2026 · 12:15',\n    status: 'receipt_needed',\n    statusLabel: 'Receipt Needed',\n    amount: '-$320.00',\n    isRefund: false,\n    hasReceipt: false,\n  },\n]\n\nconst isFiltered = computed(() => {\n  return (\n    search.value.trim() !== '' ||\n    categoryFilter.value !== 'all' ||\n    dateRangeFilter.value !== 'this_month' ||\n    statusFilter.value !== 'all'\n  )\n})\n\nconst filteredTransactions = computed(() => {\n  const query = search.value.trim().toLowerCase()\n  return transactions.filter((tx) => {\n    const matchesCategory = categoryFilter.value === 'all' || tx.categoryKey === categoryFilter.value\n    const matchesStatus = statusFilter.value === 'all' || tx.status === statusFilter.value\n    const matchesQuery =\n      !query ||\n      tx.merchant.toLowerCase().includes(query) ||\n      tx.merchantNote.toLowerCase().includes(query) ||\n      tx.category.toLowerCase().includes(query) ||\n      tx.cardholder.name.toLowerCase().includes(query) ||\n      tx.cardholder.cardLast4.includes(query)\n\n    return matchesCategory && matchesStatus && matchesQuery\n  })\n})\n\nfunction resetFilters() {\n  search.value = ''\n  categoryFilter.value = 'all'\n  dateRangeFilter.value = 'this_month'\n  statusFilter.value = 'all'\n}\n</script>\n\n<template>\n  <div data-slot=\"transaction-feed\" :class=\"cn('w-full space-y-6', props.class)\">\n    <!-- Header -->\n    <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n      <div class=\"space-y-1\">\n        <h2 class=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl\">Transactions</h2>\n        <p class=\"text-muted-foreground text-sm\">\n          Real-time ledger of card expenses, wire transfers, and subscription charges.\n        </p>\n      </div>\n      <div class=\"flex items-center gap-2.5\">\n        <Button aria-label=\"Download attachment\" variant=\"outline\" size=\"sm\">\n          <Download class=\"size-4\" aria-hidden=\"true\" />\n          Export CSV\n        </Button>\n        <Button size=\"sm\">\n          <Plus class=\"size-4\" aria-hidden=\"true\" />\n          Add Transaction\n        </Button>\n      </div>\n    </div>\n\n    <!-- 4 Financial Stat Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <Card class=\"border-border shadow-xs\">\n        <CardContent class=\"space-y-2 p-5\">\n          <div class=\"flex items-center justify-between\">\n            <p class=\"text-muted-foreground text-sm font-medium\">Total Spent This Month</p>\n            <div class=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-lg\">\n              <CreditCard class=\"size-4\" aria-hidden=\"true\" />\n            </div>\n          </div>\n          <p class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">$42,850.00</p>\n          <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n            <span class=\"text-success inline-flex items-center font-medium\">\n              <TrendingUp class=\"mr-0.5 size-3.5\" aria-hidden=\"true\" />\n              +8.4%\n            </span>\n            <span>vs previous month</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <Card class=\"border-border shadow-xs\">\n        <CardContent class=\"space-y-2 p-5\">\n          <div class=\"flex items-center justify-between\">\n            <p class=\"text-muted-foreground text-sm font-medium\">Pending Approvals</p>\n            <div class=\"bg-info/10 text-info flex size-8 items-center justify-center rounded-lg\">\n              <Clock class=\"size-4\" aria-hidden=\"true\" />\n            </div>\n          </div>\n          <p class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">6 transactions</p>\n          <p class=\"text-muted-foreground text-xs\">$3,410.00 requiring review</p>\n        </CardContent>\n      </Card>\n\n      <Card class=\"border-border shadow-xs\">\n        <CardContent class=\"space-y-2 p-5\">\n          <div class=\"flex items-center justify-between\">\n            <p class=\"text-muted-foreground text-sm font-medium\">Missing Receipts</p>\n            <Badge wrap variant=\"outline\" class=\"border-warning/30 bg-warning/10 text-warning text-xs\">\n              Action required\n            </Badge>\n          </div>\n          <p class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">3</p>\n          <p class=\"text-muted-foreground text-xs\">Total $1,618.50 unverified</p>\n        </CardContent>\n      </Card>\n\n      <Card class=\"border-border shadow-xs\">\n        <CardContent class=\"space-y-2 p-5\">\n          <div class=\"flex items-center justify-between\">\n            <p class=\"text-muted-foreground text-sm font-medium\">Average Transaction</p>\n            <div class=\"bg-muted text-muted-foreground flex size-8 items-center justify-center rounded-lg\">\n              <Receipt class=\"size-4\" aria-hidden=\"true\" />\n            </div>\n          </div>\n          <p class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">$185.20</p>\n          <p class=\"text-muted-foreground text-xs\">Across 231 card charges</p>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Filter Toolbar -->\n    <div\n      class=\"border-border bg-card flex flex-col gap-3 rounded-lg border p-3 shadow-xs md:flex-row md:items-center md:justify-between\"\n    >\n      <div class=\"flex flex-1 flex-col gap-2.5 sm:flex-row sm:items-center\">\n        <div class=\"relative min-w-0 flex-1\">\n          <Search\n            class=\"text-muted-foreground pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2\"\n            aria-hidden=\"true\"\n          />\n          <Input\n            v-model=\"search\"\n            type=\"search\"\n            placeholder=\"Search transactions...\"\n            class=\"h-9 w-full pl-9 text-xs sm:text-sm\"\n          />\n        </div>\n\n        <div class=\"flex flex-wrap items-center gap-2\">\n          <!-- Category Filter -->\n          <Select v-model=\"categoryFilter\">\n            <SelectTrigger class=\"h-9 w-full text-xs sm:w-40\">\n              <SelectValue placeholder=\"All Categories\" />\n            </SelectTrigger>\n            <SelectContent>\n              <SelectItem value=\"all\">All Categories</SelectItem>\n              <SelectItem value=\"cloud\">Cloud Hosting</SelectItem>\n              <SelectItem value=\"saas\">Software & SaaS</SelectItem>\n              <SelectItem value=\"travel\">Travel</SelectItem>\n              <SelectItem value=\"meals\">Meals & Dining</SelectItem>\n              <SelectItem value=\"office\">Office</SelectItem>\n              <SelectItem value=\"transport\">Transport</SelectItem>\n            </SelectContent>\n          </Select>\n\n          <!-- Date Range Filter -->\n          <Select v-model=\"dateRangeFilter\">\n            <SelectTrigger class=\"h-9 w-full text-xs sm:w-36\">\n              <SelectValue placeholder=\"Date Range\" />\n            </SelectTrigger>\n            <SelectContent>\n              <SelectItem value=\"this_month\">This Month</SelectItem>\n              <SelectItem value=\"last_30\">Last 30 Days</SelectItem>\n              <SelectItem value=\"last_90\">Last 90 Days</SelectItem>\n              <SelectItem value=\"ytd\">Year to Date</SelectItem>\n              <SelectItem value=\"all_time\">All Time</SelectItem>\n            </SelectContent>\n          </Select>\n\n          <!-- Status Filter -->\n          <Select v-model=\"statusFilter\">\n            <SelectTrigger class=\"h-9 w-full text-xs sm:w-36\">\n              <SelectValue placeholder=\"All Statuses\" />\n            </SelectTrigger>\n            <SelectContent>\n              <SelectItem value=\"all\">All Statuses</SelectItem>\n              <SelectItem value=\"cleared\">Cleared</SelectItem>\n              <SelectItem value=\"pending\">Pending</SelectItem>\n              <SelectItem value=\"receipt_needed\">Receipt Needed</SelectItem>\n            </SelectContent>\n          </Select>\n        </div>\n      </div>\n\n      <Button\n        v-if=\"isFiltered\"\n        variant=\"ghost\"\n        size=\"sm\"\n        class=\"text-muted-foreground hover:text-foreground h-9 self-start px-2 text-xs md:self-auto\"\n        @click=\"resetFilters\"\n      >\n        <RotateCcw class=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n        Reset filters\n      </Button>\n    </div>\n\n    <!-- Transactions Table -->\n    <div class=\"border-border bg-card overflow-hidden rounded-lg border shadow-xs\">\n      <div class=\"overflow-x-auto\">\n        <Table>\n          <TableHeader class=\"bg-muted/40\">\n            <TableRow>\n              <TableHead class=\"min-w-[220px]\">Merchant / Note</TableHead>\n              <TableHead class=\"min-w-[130px]\">Category</TableHead>\n              <TableHead class=\"min-w-[180px]\">Cardholder</TableHead>\n              <TableHead class=\"min-w-[150px]\">Date & Time</TableHead>\n              <TableHead class=\"min-w-[130px]\">Status</TableHead>\n              <TableHead class=\"min-w-[120px] text-right\">Amount</TableHead>\n              <TableHead class=\"min-w-[110px] text-center\">Receipt</TableHead>\n              <TableHead class=\"w-12 text-right\">\n                <span class=\"sr-only\">Actions</span>\n              </TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            <TableRow v-for=\"tx in filteredTransactions\" :key=\"tx.id\" class=\"hover:bg-muted/50 transition-colors\">\n              <!-- Merchant & Note -->\n              <TableCell>\n                <div class=\"flex items-center gap-3\">\n                  <div\n                    class=\"border-border/60 bg-muted/60 text-foreground flex size-9 shrink-0 items-center justify-center rounded-lg border shadow-xs\"\n                  >\n                    <component :is=\"tx.merchantIcon\" class=\"size-4\" aria-hidden=\"true\" />\n                  </div>\n                  <div class=\"min-w-0\">\n                    <p class=\"text-foreground truncate text-sm font-medium\">{{ tx.merchant }}</p>\n                    <p class=\"text-muted-foreground truncate text-xs\">{{ tx.merchantNote }}</p>\n                  </div>\n                </div>\n              </TableCell>\n\n              <!-- Category Badge -->\n              <TableCell>\n                <Badge wrap variant=\"outline\" :class=\"cn('text-xs font-normal', categoryStyles[tx.categoryKey])\">\n                  {{ tx.category }}\n                </Badge>\n              </TableCell>\n\n              <!-- Cardholder -->\n              <TableCell>\n                <div class=\"flex items-center gap-2.5\">\n                  <Avatar class=\"size-7\">\n                    <AvatarImage :src=\"tx.cardholder.avatar\" :alt=\"tx.cardholder.name\" />\n                    <AvatarFallback class=\"text-xs\">{{ tx.cardholder.initials }}</AvatarFallback>\n                  </Avatar>\n                  <div class=\"min-w-0\">\n                    <p class=\"text-foreground truncate text-xs font-medium\">{{ tx.cardholder.name }}</p>\n                    <p class=\"text-muted-foreground flex items-center gap-1 font-mono text-xs\">\n                      <span>••••</span>\n                      <span>{{ tx.cardholder.cardLast4 }}</span>\n                    </p>\n                  </div>\n                </div>\n              </TableCell>\n\n              <!-- Date & Time -->\n              <TableCell class=\"text-muted-foreground text-xs whitespace-nowrap tabular-nums\">\n                {{ tx.date }}\n              </TableCell>\n\n              <!-- Status Badge -->\n              <TableCell>\n                <Badge wrap variant=\"outline\" :class=\"cn('text-xs font-medium capitalize', statusStyles[tx.status])\">\n                  <span class=\"mr-1.5 size-1.5 rounded-full\" :class=\"statusDots[tx.status]\" aria-hidden=\"true\" />\n                  {{ tx.statusLabel }}\n                </Badge>\n              </TableCell>\n\n              <!-- Amount -->\n              <TableCell class=\"text-right text-sm font-semibold whitespace-nowrap tabular-nums\">\n                <span :class=\"tx.isRefund ? 'text-success' : 'text-foreground'\">\n                  {{ tx.amount }}\n                </span>\n              </TableCell>\n\n              <!-- Receipt Indicator -->\n              <TableCell class=\"text-center\">\n                <div class=\"flex items-center justify-center\">\n                  <span\n                    v-if=\"tx.hasReceipt\"\n                    class=\"text-muted-foreground hover:text-foreground bg-muted/60 hover:bg-muted inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors\"\n                    :title=\"tx.receiptFileName || 'View receipt'\"\n                  >\n                    <Paperclip class=\"text-muted-foreground size-3.5\" aria-hidden=\"true\" />\n                    <span>Attached</span>\n                  </span>\n                  <button\n                    v-else\n                    type=\"button\"\n                    class=\"focus-visible:ring-ring bg-warning/10 text-warning hover:bg-warning/20 text-warning inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n                  >\n                    <Upload class=\"size-3\" aria-hidden=\"true\" />\n                    <span>Upload</span>\n                  </button>\n                </div>\n              </TableCell>\n\n              <!-- Actions Dropdown -->\n              <TableCell class=\"text-right\">\n                <DropdownMenu>\n                  <DropdownMenuTrigger as-child>\n                    <Button variant=\"ghost\" size=\"icon-sm\" class=\"text-muted-foreground hover:text-foreground\">\n                      <MoreHorizontal class=\"size-4\" aria-hidden=\"true\" />\n                      <span class=\"sr-only\">Open actions for {{ tx.merchant }}</span>\n                    </Button>\n                  </DropdownMenuTrigger>\n                  <DropdownMenuContent align=\"end\" class=\"w-44\">\n                    <DropdownMenuItem class=\"cursor-pointer\">\n                      <Eye class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                      View Details\n                    </DropdownMenuItem>\n                    <DropdownMenuItem class=\"cursor-pointer\">\n                      <Paperclip class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                      {{ tx.hasReceipt ? 'View Receipt' : 'Attach Receipt' }}\n                    </DropdownMenuItem>\n                    <DropdownMenuItem class=\"cursor-pointer\">\n                      <FileCheck class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                      Match Invoice\n                    </DropdownMenuItem>\n                    <DropdownMenuSeparator />\n                    <DropdownMenuItem\n                      class=\"text-destructive focus:text-destructive focus:bg-destructive/10 cursor-pointer\"\n                    >\n                      <ShieldAlert class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                      Dispute\n                    </DropdownMenuItem>\n                  </DropdownMenuContent>\n                </DropdownMenu>\n              </TableCell>\n            </TableRow>\n\n            <!-- Empty State Row -->\n            <TableRow v-if=\"filteredTransactions.length === 0\">\n              <TableCell :colspan=\"8\" class=\"h-36 text-center\">\n                <div class=\"flex flex-col items-center justify-center gap-2\">\n                  <Search class=\"text-muted-foreground/50 size-6\" aria-hidden=\"true\" />\n                  <p class=\"text-foreground text-sm font-medium\">No transactions match your filters</p>\n                  <p class=\"text-muted-foreground text-xs\">Try clearing your search query or reset category/status</p>\n                  <Button variant=\"outline\" size=\"sm\" class=\"mt-2 text-xs\" @click=\"resetFilters\">\n                    Reset filters\n                  </Button>\n                </div>\n              </TableCell>\n            </TableRow>\n          </TableBody>\n        </Table>\n      </div>\n\n      <!-- Pagination footer strip -->\n      <div\n        class=\"border-border bg-card text-muted-foreground flex flex-col items-center justify-between gap-3 border-t px-4 py-3 text-xs sm:flex-row\"\n      >\n        <p class=\"tabular-nums\">\n          Showing <span class=\"text-foreground font-medium\">{{ filteredTransactions.length }}</span> of\n          <span class=\"text-foreground font-medium\">{{ transactions.length }}</span> transactions\n        </p>\n        <div class=\"flex items-center gap-2\">\n          <Button variant=\"outline\" size=\"sm\" class=\"h-8 text-xs\" disabled> Previous </Button>\n          <Button variant=\"outline\" size=\"sm\" class=\"h-8 text-xs\" disabled> Next </Button>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/TransactionFeed.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/avatar.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/dropdown-menu.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/select.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Brex/Ramp-style real-time corporate transaction feed with expense categorization, summary financial stat cards, search and filter toolbar, cardholder metadata, receipt attachment triggers, and row action menus.",
  "categories": [
    "finance",
    "app",
    "billing"
  ]
}