{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "transaction-feed",
  "title": "Transaction Feed",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/transaction-feed/TransactionFeed.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\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-react'\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: React.ElementType\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 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\nexport function TransactionFeed({ className }: { className?: string }) {\n  const [search, setSearch] = React.useState('')\n  const [categoryFilter, setCategoryFilter] = React.useState('all')\n  const [dateRangeFilter, setDateRangeFilter] = React.useState('this_month')\n  const [statusFilter, setStatusFilter] = React.useState('all')\n\n  const isFiltered =\n    search.trim() !== '' || categoryFilter !== 'all' || dateRangeFilter !== 'this_month' || statusFilter !== 'all'\n\n  const filteredTransactions = React.useMemo(() => {\n    const query = search.trim().toLowerCase()\n    return transactions.filter((tx) => {\n      const matchesCategory = categoryFilter === 'all' || tx.categoryKey === categoryFilter\n      const matchesStatus = statusFilter === 'all' || tx.status === statusFilter\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  }, [search, categoryFilter, statusFilter])\n\n  const resetFilters = () => {\n    setSearch('')\n    setCategoryFilter('all')\n    setDateRangeFilter('this_month')\n    setStatusFilter('all')\n  }\n\n  return (\n    <div data-slot=\"transaction-feed\" className={cn('w-full space-y-6', className)}>\n      {/* Header */}\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div className=\"space-y-1\">\n          <h2 className=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl\">Transactions</h2>\n          <p className=\"text-muted-foreground text-sm\">\n            Real-time ledger of card expenses, wire transfers, and subscription charges.\n          </p>\n        </div>\n        <div className=\"flex items-center gap-2.5\">\n          <Button aria-label=\"Download attachment\" variant=\"outline\" size=\"sm\">\n            <Download className=\"size-4\" aria-hidden=\"true\" />\n            Export CSV\n          </Button>\n          <Button size=\"sm\">\n            <Plus className=\"size-4\" aria-hidden=\"true\" />\n            Add Transaction\n          </Button>\n        </div>\n      </div>\n\n      {/* 4 Financial Stat Cards */}\n      <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        <Card className=\"border-border shadow-xs\">\n          <CardContent className=\"space-y-2 p-5\">\n            <div className=\"flex items-center justify-between\">\n              <p className=\"text-muted-foreground text-sm font-medium\">Total Spent This Month</p>\n              <div className=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-lg\">\n                <CreditCard className=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <p className=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">$42,850.00</p>\n            <div className=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n              <span className=\"text-success inline-flex items-center font-medium\">\n                <TrendingUp className=\"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 className=\"border-border shadow-xs\">\n          <CardContent className=\"space-y-2 p-5\">\n            <div className=\"flex items-center justify-between\">\n              <p className=\"text-muted-foreground text-sm font-medium\">Pending Approvals</p>\n              <div className=\"bg-info/10 text-info flex size-8 items-center justify-center rounded-lg\">\n                <Clock className=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <p className=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">6 transactions</p>\n            <p className=\"text-muted-foreground text-xs\">$3,410.00 requiring review</p>\n          </CardContent>\n        </Card>\n\n        <Card className=\"border-border shadow-xs\">\n          <CardContent className=\"space-y-2 p-5\">\n            <div className=\"flex items-center justify-between\">\n              <p className=\"text-muted-foreground text-sm font-medium\">Missing Receipts</p>\n              <Badge wrap variant=\"outline\" className=\"border-warning/30 bg-warning/10 text-warning text-xs\">\n                Action required\n              </Badge>\n            </div>\n            <p className=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">3</p>\n            <p className=\"text-muted-foreground text-xs\">Total $1,618.50 unverified</p>\n          </CardContent>\n        </Card>\n\n        <Card className=\"border-border shadow-xs\">\n          <CardContent className=\"space-y-2 p-5\">\n            <div className=\"flex items-center justify-between\">\n              <p className=\"text-muted-foreground text-sm font-medium\">Average Transaction</p>\n              <div className=\"bg-muted text-muted-foreground flex size-8 items-center justify-center rounded-lg\">\n                <Receipt className=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <p className=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">$185.20</p>\n            <p className=\"text-muted-foreground text-xs\">Across 231 card charges</p>\n          </CardContent>\n        </Card>\n      </div>\n\n      {/* Filter Toolbar */}\n      <div className=\"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        <div className=\"flex flex-1 flex-col gap-2.5 sm:flex-row sm:items-center\">\n          <div className=\"relative min-w-0 flex-1\">\n            <Search\n              className=\"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              value={search}\n              onChange={(e) => setSearch(e.target.value)}\n              type=\"search\"\n              placeholder=\"Search transactions...\"\n              className=\"h-9 w-full pl-9 text-xs sm:text-sm\"\n            />\n          </div>\n\n          <div className=\"flex flex-wrap items-center gap-2\">\n            {/* Category Filter */}\n            <Select value={categoryFilter} onValueChange={setCategoryFilter}>\n              <SelectTrigger className=\"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 value={dateRangeFilter} onValueChange={setDateRangeFilter}>\n              <SelectTrigger className=\"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 value={statusFilter} onValueChange={setStatusFilter}>\n              <SelectTrigger className=\"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        {isFiltered && (\n          <Button\n            variant=\"ghost\"\n            size=\"sm\"\n            className=\"text-muted-foreground hover:text-foreground h-9 self-start px-2 text-xs md:self-auto\"\n            onClick={resetFilters}\n          >\n            <RotateCcw className=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n            Reset filters\n          </Button>\n        )}\n      </div>\n\n      {/* Transactions Table */}\n      <div className=\"border-border bg-card overflow-hidden rounded-lg border shadow-xs\">\n        <div className=\"overflow-x-auto\">\n          <Table>\n            <TableHeader className=\"bg-muted/40\">\n              <TableRow>\n                <TableHead className=\"min-w-[220px]\">Merchant / Note</TableHead>\n                <TableHead className=\"min-w-[130px]\">Category</TableHead>\n                <TableHead className=\"min-w-[180px]\">Cardholder</TableHead>\n                <TableHead className=\"min-w-[150px]\">Date & Time</TableHead>\n                <TableHead className=\"min-w-[130px]\">Status</TableHead>\n                <TableHead className=\"min-w-[120px] text-right\">Amount</TableHead>\n                <TableHead className=\"min-w-[110px] text-center\">Receipt</TableHead>\n                <TableHead className=\"w-12 text-right\">\n                  <span className=\"sr-only\">Actions</span>\n                </TableHead>\n              </TableRow>\n            </TableHeader>\n            <TableBody>\n              {filteredTransactions.map((tx) => {\n                const MerchantIcon = tx.merchantIcon\n                return (\n                  <TableRow key={tx.id} className=\"hover:bg-muted/50 transition-colors\">\n                    {/* Merchant & Note */}\n                    <TableCell>\n                      <div className=\"flex items-center gap-3\">\n                        <div className=\"border-border/60 bg-muted/60 text-foreground flex size-9 shrink-0 items-center justify-center rounded-lg border shadow-xs\">\n                          <MerchantIcon className=\"size-4\" aria-hidden=\"true\" />\n                        </div>\n                        <div className=\"min-w-0\">\n                          <p className=\"text-foreground truncate text-sm font-medium\">{tx.merchant}</p>\n                          <p className=\"text-muted-foreground truncate text-xs\">{tx.merchantNote}</p>\n                        </div>\n                      </div>\n                    </TableCell>\n\n                    {/* Category Badge */}\n                    <TableCell>\n                      <Badge variant=\"outline\" className={cn('text-xs font-normal', categoryStyles[tx.categoryKey])}>\n                        {tx.category}\n                      </Badge>\n                    </TableCell>\n\n                    {/* Cardholder */}\n                    <TableCell>\n                      <div className=\"flex items-center gap-2.5\">\n                        <Avatar className=\"size-7\">\n                          <AvatarImage src={tx.cardholder.avatar} alt={tx.cardholder.name} />\n                          <AvatarFallback className=\"text-xs\">{tx.cardholder.initials}</AvatarFallback>\n                        </Avatar>\n                        <div className=\"min-w-0\">\n                          <p className=\"text-foreground truncate text-xs font-medium\">{tx.cardholder.name}</p>\n                          <p className=\"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 className=\"text-muted-foreground text-xs whitespace-nowrap tabular-nums\">\n                      {tx.date}\n                    </TableCell>\n\n                    {/* Status Badge */}\n                    <TableCell>\n                      <Badge\n                        variant=\"outline\"\n                        className={cn('text-xs font-medium capitalize', statusStyles[tx.status])}\n                      >\n                        <span\n                          className={cn('mr-1.5 size-1.5 rounded-full', statusDots[tx.status])}\n                          aria-hidden=\"true\"\n                        />\n                        {tx.statusLabel}\n                      </Badge>\n                    </TableCell>\n\n                    {/* Amount */}\n                    <TableCell className=\"text-right text-sm font-semibold whitespace-nowrap tabular-nums\">\n                      <span className={tx.isRefund ? 'text-success' : 'text-foreground'}>{tx.amount}</span>\n                    </TableCell>\n\n                    {/* Receipt Indicator */}\n                    <TableCell className=\"text-center\">\n                      <div className=\"flex items-center justify-center\">\n                        {tx.hasReceipt ? (\n                          <span\n                            className=\"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 className=\"text-muted-foreground size-3.5\" aria-hidden=\"true\" />\n                            <span>Attached</span>\n                          </span>\n                        ) : (\n                          <button\n                            type=\"button\"\n                            className=\"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 className=\"size-3\" aria-hidden=\"true\" />\n                            <span>Upload</span>\n                          </button>\n                        )}\n                      </div>\n                    </TableCell>\n\n                    {/* Actions Dropdown */}\n                    <TableCell className=\"text-right\">\n                      <DropdownMenu>\n                        <DropdownMenuTrigger asChild>\n                          <Button\n                            variant=\"ghost\"\n                            size=\"icon-sm\"\n                            className=\"text-muted-foreground hover:text-foreground\"\n                          >\n                            <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n                            <span className=\"sr-only\">Open actions for {tx.merchant}</span>\n                          </Button>\n                        </DropdownMenuTrigger>\n                        <DropdownMenuContent align=\"end\" className=\"w-44\">\n                          <DropdownMenuItem className=\"cursor-pointer\">\n                            <Eye className=\"mr-2 size-4\" aria-hidden=\"true\" />\n                            View Details\n                          </DropdownMenuItem>\n                          <DropdownMenuItem className=\"cursor-pointer\">\n                            <Paperclip className=\"mr-2 size-4\" aria-hidden=\"true\" />\n                            {tx.hasReceipt ? 'View Receipt' : 'Attach Receipt'}\n                          </DropdownMenuItem>\n                          <DropdownMenuItem className=\"cursor-pointer\">\n                            <FileCheck className=\"mr-2 size-4\" aria-hidden=\"true\" />\n                            Match Invoice\n                          </DropdownMenuItem>\n                          <DropdownMenuSeparator />\n                          <DropdownMenuItem className=\"text-destructive focus:text-destructive focus:bg-destructive/10 cursor-pointer\">\n                            <ShieldAlert className=\"mr-2 size-4\" aria-hidden=\"true\" />\n                            Dispute\n                          </DropdownMenuItem>\n                        </DropdownMenuContent>\n                      </DropdownMenu>\n                    </TableCell>\n                  </TableRow>\n                )\n              })}\n\n              {/* Empty State Row */}\n              {filteredTransactions.length === 0 && (\n                <TableRow>\n                  <TableCell colSpan={8} className=\"h-36 text-center\">\n                    <div className=\"flex flex-col items-center justify-center gap-2\">\n                      <Search className=\"text-muted-foreground/50 size-6\" aria-hidden=\"true\" />\n                      <p className=\"text-foreground text-sm font-medium\">No transactions match your filters</p>\n                      <p className=\"text-muted-foreground text-xs\">\n                        Try clearing your search query or reset category/status\n                      </p>\n                      <Button variant=\"outline\" size=\"sm\" className=\"mt-2 text-xs\" onClick={resetFilters}>\n                        Reset filters\n                      </Button>\n                    </div>\n                  </TableCell>\n                </TableRow>\n              )}\n            </TableBody>\n          </Table>\n        </div>\n\n        {/* Pagination footer strip */}\n        <div className=\"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          <p className=\"tabular-nums\">\n            Showing <span className=\"text-foreground font-medium\">{filteredTransactions.length}</span> of{' '}\n            <span className=\"text-foreground font-medium\">{transactions.length}</span> transactions\n          </p>\n          <div className=\"flex items-center gap-2\">\n            <Button variant=\"outline\" size=\"sm\" className=\"h-8 text-xs\" disabled>\n              Previous\n            </Button>\n            <Button variant=\"outline\" size=\"sm\" className=\"h-8 text-xs\" disabled>\n              Next\n            </Button>\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/TransactionFeed.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/avatar.json",
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/dropdown-menu.json",
    "https://uipkge.dev/r/react/input.json",
    "https://uipkge.dev/r/react/select.json",
    "https://uipkge.dev/r/react/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"
  ]
}