{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table-05",
  "type": "registry:block",
  "title": "Data Table",
  "description": "A data table block.",
  "author": "ephraim duncan <https://ephraimduncan.com>",
  "registryDependencies": [
    "badge",
    "button",
    "checkbox",
    "dropdown-menu",
    "input",
    "select",
    "table"
  ],
  "dependencies": [
    "@tanstack/react-table",
    "lucide-react"
  ],
  "files": [
    {
      "path": "content/components/tables/table-05.tsx",
      "type": "registry:component",
      "target": "components/table-05.tsx",
      "content": "'use client';\n\nimport {\n  type ColumnDef,\n  flexRender,\n  getCoreRowModel,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  type SortingState,\n  useReactTable,\n} from '@tanstack/react-table';\nimport {\n  ChevronLeft,\n  ChevronRight,\n  Eye,\n  MoreHorizontal,\n  Pencil,\n  Trash2,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Input } from '@/components/ui/input';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\ntype Status = 'completed' | 'pending' | 'processing' | 'cancelled';\n\ninterface Item {\n  id: string;\n  name: string;\n  date: string;\n  status: Status;\n  amount: string;\n}\n\nconst statusConfig: Record<Status, { label: string; className: string }> = {\n  completed: {\n    label: 'Completed',\n    className:\n      'bg-emerald-500/15 text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-400',\n  },\n  pending: {\n    label: 'Pending',\n    className:\n      'bg-amber-500/15 text-amber-700 dark:bg-amber-500/10 dark:text-amber-400',\n  },\n  processing: {\n    label: 'Processing',\n    className:\n      'bg-blue-500/15 text-blue-700 dark:bg-blue-500/10 dark:text-blue-400',\n  },\n  cancelled: {\n    label: 'Cancelled',\n    className:\n      'bg-rose-500/15 text-rose-700 dark:bg-rose-500/10 dark:text-rose-400',\n  },\n};\n\nfunction StatusBadge({ status }: { status: Status }) {\n  const config = statusConfig[status];\n  return (\n    <Badge className={cn('border-0', config.className)} variant=\"outline\">\n      {config.label}\n    </Badge>\n  );\n}\n\nconst columns: ColumnDef<Item>[] = [\n  {\n    id: 'select',\n    header: ({ table }) => (\n      <Checkbox\n        aria-label=\"Select all\"\n        checked={table.getIsAllPageRowsSelected()}\n        indeterminate={\n          table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected()\n        }\n        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n      />\n    ),\n    cell: ({ row }) => (\n      <Checkbox\n        aria-label=\"Select row\"\n        checked={row.getIsSelected()}\n        onCheckedChange={(value) => row.toggleSelected(!!value)}\n      />\n    ),\n    enableSorting: false,\n    enableHiding: false,\n  },\n  {\n    accessorKey: 'name',\n    header: 'Name',\n    cell: ({ row }) => (\n      <span className=\"font-medium\">{row.getValue('name')}</span>\n    ),\n  },\n  {\n    accessorKey: 'date',\n    header: 'Date',\n  },\n  {\n    accessorKey: 'status',\n    header: 'Status',\n    cell: ({ row }) => <StatusBadge status={row.getValue('status')} />,\n  },\n  {\n    accessorKey: 'amount',\n    header: () => <div className=\"text-right\">Amount</div>,\n    cell: ({ row }) => (\n      <div className=\"text-right font-medium\">{row.getValue('amount')}</div>\n    ),\n  },\n  {\n    id: 'actions',\n    cell: () => (\n      <div className=\"text-right\">\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={<Button className=\"h-8 w-8\" size=\"icon\" variant=\"ghost\" />}\n          >\n            <MoreHorizontal className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Open menu</span>\n          </DropdownMenuTrigger>\n          <DropdownMenuContent align=\"end\">\n            <DropdownMenuItem>\n              <Eye className=\"mr-2 h-4 w-4\" />\n              View details\n            </DropdownMenuItem>\n            <DropdownMenuItem>\n              <Pencil className=\"mr-2 h-4 w-4\" />\n              Edit\n            </DropdownMenuItem>\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className=\"text-destructive\">\n              <Trash2 className=\"mr-2 h-4 w-4\" />\n              Delete\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </div>\n    ),\n  },\n];\n\nconst data: Item[] = [\n  {\n    id: '1',\n    name: 'Project Alpha',\n    date: 'Jan 15, 2024',\n    status: 'completed',\n    amount: '$2,500',\n  },\n  {\n    id: '2',\n    name: 'Website Redesign',\n    date: 'Feb 3, 2024',\n    status: 'processing',\n    amount: '$4,200',\n  },\n  {\n    id: '3',\n    name: 'Mobile App MVP',\n    date: 'Feb 18, 2024',\n    status: 'pending',\n    amount: '$8,750',\n  },\n  {\n    id: '4',\n    name: 'Brand Identity',\n    date: 'Mar 5, 2024',\n    status: 'completed',\n    amount: '$1,800',\n  },\n  {\n    id: '5',\n    name: 'Marketing Campaign',\n    date: 'Mar 22, 2024',\n    status: 'cancelled',\n    amount: '$3,400',\n  },\n  {\n    id: '6',\n    name: 'Analytics Dashboard',\n    date: 'Apr 8, 2024',\n    status: 'processing',\n    amount: '$5,600',\n  },\n  {\n    id: '7',\n    name: 'E-commerce Platform',\n    date: 'Apr 25, 2024',\n    status: 'pending',\n    amount: '$12,000',\n  },\n  {\n    id: '8',\n    name: 'API Integration',\n    date: 'May 10, 2024',\n    status: 'completed',\n    amount: '$3,200',\n  },\n];\n\nexport default function Table05() {\n  const [sorting, setSorting] = useState<SortingState>([]);\n  const [rowSelection, setRowSelection] = useState({});\n  const [globalFilter, setGlobalFilter] = useState('');\n\n  const table = useReactTable({\n    data,\n    columns,\n    getCoreRowModel: getCoreRowModel(),\n    getPaginationRowModel: getPaginationRowModel(),\n    getSortedRowModel: getSortedRowModel(),\n    getFilteredRowModel: getFilteredRowModel(),\n    onSortingChange: setSorting,\n    onRowSelectionChange: setRowSelection,\n    onGlobalFilterChange: setGlobalFilter,\n    globalFilterFn: 'includesString',\n    state: {\n      sorting,\n      rowSelection,\n      globalFilter,\n    },\n    initialState: {\n      pagination: { pageSize: 5 },\n    },\n  });\n\n  const pageCount = table.getPageCount();\n  const currentPage = table.getState().pagination.pageIndex + 1;\n\n  return (\n    <div className=\"w-full max-w-3xl space-y-4\">\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div className=\"flex items-center gap-2\">\n          <span className=\"text-muted-foreground text-sm\">Show</span>\n          <Select\n            onValueChange={(value) => table.setPageSize(Number(value))}\n            value={String(table.getState().pagination.pageSize)}\n          >\n            <SelectTrigger className=\"h-8 w-16\">\n              <SelectValue />\n            </SelectTrigger>\n            <SelectContent>\n              {[5, 10, 20].map((size) => (\n                <SelectItem key={size} value={String(size)}>\n                  {size}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n          <span className=\"text-muted-foreground text-sm\">entries</span>\n        </div>\n        <Input\n          className=\"h-8 w-full sm:w-64\"\n          onChange={(e) => setGlobalFilter(e.target.value)}\n          placeholder=\"Search...\"\n          value={globalFilter}\n        />\n      </div>\n\n      <div className=\"rounded-lg border\">\n        <Table>\n          <TableHeader>\n            {table.getHeaderGroups().map((headerGroup) => (\n              <TableRow key={headerGroup.id}>\n                {headerGroup.headers.map((header) => (\n                  <TableHead key={header.id}>\n                    {header.isPlaceholder\n                      ? null\n                      : flexRender(\n                          header.column.columnDef.header,\n                          header.getContext()\n                        )}\n                  </TableHead>\n                ))}\n              </TableRow>\n            ))}\n          </TableHeader>\n          <TableBody>\n            {table.getRowModel().rows.length ? (\n              table.getRowModel().rows.map((row) => (\n                <TableRow\n                  data-state={row.getIsSelected() && 'selected'}\n                  key={row.id}\n                >\n                  {row.getVisibleCells().map((cell) => (\n                    <TableCell key={cell.id}>\n                      {flexRender(\n                        cell.column.columnDef.cell,\n                        cell.getContext()\n                      )}\n                    </TableCell>\n                  ))}\n                </TableRow>\n              ))\n            ) : (\n              <TableRow>\n                <TableCell\n                  className=\"h-24 text-center\"\n                  colSpan={columns.length}\n                >\n                  No results.\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        </Table>\n      </div>\n\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <p className=\"text-pretty text-muted-foreground text-sm\">\n          Showing{' '}\n          {table.getState().pagination.pageIndex *\n            table.getState().pagination.pageSize +\n            1}{' '}\n          to{' '}\n          {Math.min(\n            (table.getState().pagination.pageIndex + 1) *\n              table.getState().pagination.pageSize,\n            table.getFilteredRowModel().rows.length\n          )}{' '}\n          of {table.getFilteredRowModel().rows.length} entries\n        </p>\n        <div className=\"flex items-center gap-1\">\n          <Button\n            aria-label=\"Previous page\"\n            className=\"h-8 w-8\"\n            disabled={!table.getCanPreviousPage()}\n            onClick={() => table.previousPage()}\n            size=\"icon\"\n            variant=\"outline\"\n          >\n            <ChevronLeft className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Previous page</span>\n          </Button>\n          {Array.from({ length: pageCount }, (_, i) => i + 1).map((page) => (\n            <Button\n              aria-label={`Go to page ${page}`}\n              className=\"h-8 w-8\"\n              key={page}\n              onClick={() => table.setPageIndex(page - 1)}\n              size=\"icon\"\n              variant={currentPage === page ? 'default' : 'outline'}\n            >\n              {page}\n            </Button>\n          ))}\n          <Button\n            aria-label=\"Next page\"\n            className=\"h-8 w-8\"\n            disabled={!table.getCanNextPage()}\n            onClick={() => table.nextPage()}\n            size=\"icon\"\n            variant=\"outline\"\n          >\n            <ChevronRight className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Next page</span>\n          </Button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
    }
  ],
  "categories": [
    "tables"
  ]
}