{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pool-table",
  "title": "Pool Table",
  "description": "A sortable table of liquidity pools with token icon groups, TVL, volume, APY, and rewards columns.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "table",
    "https://solanaui.dev/r/token-icon-group.json",
    "https://solanaui.dev/r/sol-lib-sort-utils.json"
  ],
  "files": [
    {
      "path": "src/registry/sol/pool-table.tsx",
      "content": "\"use client\";\n\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport React from \"react\";\nimport { TokenIconGroup } from \"@/registry/sol/token-icon-group\";\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from \"@/components/ui/table\";\nimport type { SortDirection } from \"@/registry/lib/sort-utils\";\nimport { compareValues } from \"@/registry/lib/sort-utils\";\nimport { cn } from \"@/lib/utils\";\n\ninterface PoolTableColumn {\n  key: string;\n  label: string;\n  className?: string;\n}\n\ninterface PoolTableRow {\n  icons: { src: string; alt?: string }[];\n  name?: string;\n  data: Record<string, string>;\n}\n\ninterface PoolTableProps {\n  columns: PoolTableColumn[];\n  rows: PoolTableRow[];\n  actions?: React.ReactNode[];\n  className?: string;\n}\n\nconst PoolTable = ({ columns, rows, actions, className }: PoolTableProps) => {\n  const showActions = actions && actions.length > 0;\n  const [sortKey, setSortKey] = React.useState<string | null>(null);\n  const [sortDirection, setSortDirection] = React.useState<SortDirection>(null);\n\n  const handleSort = (key: string) => {\n    if (sortKey !== key) {\n      setSortKey(key);\n      setSortDirection(\"asc\");\n    } else if (sortDirection === \"asc\") {\n      setSortDirection(\"desc\");\n    } else {\n      setSortKey(null);\n      setSortDirection(null);\n    }\n  };\n\n  const sortedIndices = React.useMemo(() => {\n    const indices = rows.map((_, i) => i);\n    if (!sortKey || !sortDirection) return indices;\n\n    return indices.sort((a, b) => {\n      let valA: string;\n      let valB: string;\n\n      if (sortKey === \"__name__\") {\n        valA =\n          rows[a].name ??\n          rows[a].icons\n            .map((t) => t.alt)\n            .filter(Boolean)\n            .join(\"/\");\n        valB =\n          rows[b].name ??\n          rows[b].icons\n            .map((t) => t.alt)\n            .filter(Boolean)\n            .join(\"/\");\n      } else {\n        valA = rows[a].data[sortKey] ?? \"\";\n        valB = rows[b].data[sortKey] ?? \"\";\n      }\n\n      const result = compareValues(valA, valB);\n      return sortDirection === \"desc\" ? -result : result;\n    });\n  }, [rows, sortKey, sortDirection]);\n\n  return (\n    <Table className={className}>\n      <TableHeader>\n        <TableRow>\n          <TableHead>\n            <button\n              type=\"button\"\n              onClick={() => handleSort(\"__name__\")}\n              className={cn(\n                \"inline-flex items-center gap-1 cursor-pointer hover:text-foreground transition-colors\",\n                sortKey === \"__name__\"\n                  ? \"text-foreground\"\n                  : \"text-muted-foreground\",\n              )}\n            >\n              Name\n              {sortKey === \"__name__\" && sortDirection === \"asc\" && (\n                <ChevronUpIcon className=\"size-3.5\" />\n              )}\n              {sortKey === \"__name__\" && sortDirection === \"desc\" && (\n                <ChevronDownIcon className=\"size-3.5\" />\n              )}\n            </button>\n          </TableHead>\n          {columns.map((col) => {\n            const isActive = sortKey === col.key;\n            return (\n              <TableHead key={col.key} className={col.className}>\n                <button\n                  type=\"button\"\n                  onClick={() => handleSort(col.key)}\n                  className={cn(\n                    \"inline-flex items-center gap-1 cursor-pointer hover:text-foreground transition-colors\",\n                    isActive ? \"text-foreground\" : \"text-muted-foreground\",\n                  )}\n                >\n                  {col.label}\n                  {isActive && sortDirection === \"asc\" && (\n                    <ChevronUpIcon className=\"size-3.5\" />\n                  )}\n                  {isActive && sortDirection === \"desc\" && (\n                    <ChevronDownIcon className=\"size-3.5\" />\n                  )}\n                </button>\n              </TableHead>\n            );\n          })}\n          {showActions && <TableHead className=\"text-right\" />}\n        </TableRow>\n      </TableHeader>\n      <TableBody>\n        {sortedIndices.map((originalIndex) => {\n          const row = rows[originalIndex];\n          const rowName =\n            row.name ??\n            row.icons\n              .map((t) => t.alt)\n              .filter(Boolean)\n              .join(\"/\");\n\n          return (\n            <TableRow\n              key={`${rowName}-${row.data[columns[0]?.key] ?? originalIndex}`}\n            >\n              <TableCell>\n                <div className=\"flex items-center gap-2\">\n                  <TokenIconGroup\n                    tokens={row.icons}\n                    size={20}\n                    overlap={row.icons.length > 1 ? -6 : 0}\n                  />\n                  <span className=\"font-medium\">{rowName}</span>\n                </div>\n              </TableCell>\n              {columns.map((col) => (\n                <TableCell key={col.key} className={cn(col.className)}>\n                  {row.data[col.key] ?? \"-\"}\n                </TableCell>\n              ))}\n              {showActions && actions[originalIndex] && (\n                <TableCell className=\"text-right\">\n                  {actions[originalIndex]}\n                </TableCell>\n              )}\n            </TableRow>\n          );\n        })}\n      </TableBody>\n    </Table>\n  );\n};\n\nexport type { PoolTableProps, PoolTableRow, PoolTableColumn };\nexport { PoolTable };\n",
      "type": "registry:component",
      "target": "components/sol/pool-table.tsx"
    }
  ],
  "type": "registry:component"
}