{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-table2",
  "title": "Data table",
  "description": "Powerful table and datagrids built using TanStack Table.",
  "files": [
    {
      "path": "contents/components/data-table/2/index.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport {\n  flexRender,\n  getCoreRowModel,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  useReactTable,\n  type ColumnDef,\n  type ColumnFiltersState,\n  type ExpandedState,\n  type RowSelectionState,\n  type SortingState,\n  type VisibilityState\n} from \"@tanstack/react-table\";\nimport {\n  ArrowUpDown,\n  ChevronDown,\n  ChevronRight,\n  ColumnsIcon,\n  MoreHorizontal,\n  SearchIcon,\n  Trash2,\n  Download,\n  Copy,\n  FileText\n} from \"lucide-react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n  DropdownMenu,\n  DropdownMenuCheckboxItem,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\";\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow\n} from \"@/components/ui/table\";\nimport { InputGroup, InputGroupInput, InputGroupAddon } from \"@/components/ui/input-group\";\n\nfunction formatCurrency(amount: number, currency = \"USD\") {\n  return new Intl.NumberFormat(\"en-US\", { style: \"currency\", currency }).format(amount);\n}\n\nconst data = [\n  {\n    id: \"ord_m5gr84i9\",\n    orderNumber: \"SO-1001\",\n    status: \"processing\",\n    createdAt: \"2024-01-15\",\n    customer: {\n      name: \"Ken Adams\",\n      email: \"ken99@example.com\"\n    },\n    payment: {\n      method: \"Card\",\n      last4: \"4242\",\n      status: \"paid\"\n    },\n    shipping: {\n      method: \"Standard\",\n      address: \"123 Main St, New York, NY\"\n    },\n    totals: {\n      currency: \"USD\",\n      subtotal: 316,\n      shipping: 12,\n      tax: 24,\n      total: 352\n    },\n    items: [\n      { sku: \"SKU-001\", name: \"Starter Kit\", quantity: 1, unitPrice: 199 },\n      { sku: \"SKU-014\", name: \"Pro Components Pack\", quantity: 1, unitPrice: 117 }\n    ]\n  },\n  {\n    id: \"ord_3u1reuv4\",\n    orderNumber: \"SO-1002\",\n    status: \"fulfilled\",\n    createdAt: \"2024-01-16\",\n    customer: {\n      name: \"Abe Stone\",\n      email: \"abe45@example.com\"\n    },\n    payment: {\n      method: \"PayPal\",\n      last4: null,\n      status: \"paid\"\n    },\n    shipping: {\n      method: \"Express\",\n      address: \"456 Oak Ave, Los Angeles, CA\"\n    },\n    totals: {\n      currency: \"USD\",\n      subtotal: 242,\n      shipping: 18,\n      tax: 19,\n      total: 279\n    },\n    items: [{ sku: \"SKU-008\", name: \"Marketing Blocks Bundle\", quantity: 1, unitPrice: 242 }]\n  },\n  {\n    id: \"ord_derv1ws0\",\n    orderNumber: \"SO-1003\",\n    status: \"pending\",\n    createdAt: \"2024-01-17\",\n    customer: {\n      name: \"Monserrat Lee\",\n      email: \"monserrat44@example.com\"\n    },\n    payment: {\n      method: \"Card\",\n      last4: \"0101\",\n      status: \"unpaid\"\n    },\n    shipping: {\n      method: \"Standard\",\n      address: \"789 Pine Rd, Chicago, IL\"\n    },\n    totals: {\n      currency: \"USD\",\n      subtotal: 837,\n      shipping: 0,\n      tax: 67,\n      total: 904\n    },\n    items: [\n      { sku: \"SKU-021\", name: \"Ecommerce Blocks\", quantity: 1, unitPrice: 399 },\n      { sku: \"SKU-033\", name: \"Dashboard Template\", quantity: 1, unitPrice: 438 }\n    ]\n  },\n  {\n    id: \"ord_5kma53ae\",\n    orderNumber: \"SO-1004\",\n    status: \"fulfilled\",\n    createdAt: \"2024-01-18\",\n    customer: {\n      name: \"Silas Chen\",\n      email: \"silas22@example.com\"\n    },\n    payment: {\n      method: \"Card\",\n      last4: \"7284\",\n      status: \"paid\"\n    },\n    shipping: {\n      method: \"Standard\",\n      address: \"321 Elm St, Houston, TX\"\n    },\n    totals: {\n      currency: \"USD\",\n      subtotal: 874,\n      shipping: 14,\n      tax: 71,\n      total: 959\n    },\n    items: [\n      { sku: \"SKU-055\", name: \"Full UI Kit\", quantity: 1, unitPrice: 599 },\n      { sku: \"SKU-089\", name: \"Premium Support (1 month)\", quantity: 1, unitPrice: 275 }\n    ]\n  },\n  {\n    id: \"ord_bhqecj4p\",\n    orderNumber: \"SO-1005\",\n    status: \"cancelled\",\n    createdAt: \"2024-01-19\",\n    customer: {\n      name: \"Carmella Diaz\",\n      email: \"carmella@example.com\"\n    },\n    payment: {\n      method: \"Card\",\n      last4: \"1193\",\n      status: \"refunded\"\n    },\n    shipping: {\n      method: \"Standard\",\n      address: \"654 Maple Dr, Phoenix, AZ\"\n    },\n    totals: {\n      currency: \"USD\",\n      subtotal: 721,\n      shipping: 0,\n      tax: 0,\n      total: 721\n    },\n    items: [{ sku: \"SKU-034\", name: \"Templates Pack\", quantity: 1, unitPrice: 721 }]\n  }\n];\n\nexport type Order = (typeof data)[number];\n\nexport const columns: ColumnDef<Order>[] = [\n  {\n    id: \"expand\",\n    header: () => null,\n    cell: ({ row }) => (\n      <Button\n        variant=\"ghost\"\n        size=\"sm\"\n        onClick={(event) => {\n          event.stopPropagation();\n          row.toggleExpanded();\n        }}\n        aria-label={row.getIsExpanded() ? \"Collapse row\" : \"Expand row\"}\n        className=\"h-8 w-8 p-0\">\n        <ChevronRight\n          className={`transition-transform ${row.getIsExpanded() ? \"rotate-90\" : \"\"}`}\n        />\n      </Button>\n    ),\n    enableSorting: false,\n    enableHiding: false\n  },\n  {\n    id: \"select\",\n    header: ({ table }) => (\n      <div onClick={(event) => event.stopPropagation()}>\n        <Checkbox\n          checked={\n            table.getIsAllPageRowsSelected() ||\n            (table.getIsSomePageRowsSelected() && \"indeterminate\")\n          }\n          onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n          aria-label=\"Select all\"\n        />\n      </div>\n    ),\n    cell: ({ row }) => (\n      <div onClick={(event) => event.stopPropagation()}>\n        <Checkbox\n          checked={row.getIsSelected()}\n          onCheckedChange={(value) => row.toggleSelected(!!value)}\n          aria-label=\"Select row\"\n        />\n      </div>\n    ),\n    enableSorting: false,\n    enableHiding: false\n  },\n  {\n    accessorKey: \"orderNumber\",\n    header: ({ column }) => (\n      <Button variant=\"ghost\" onClick={() => column.toggleSorting(column.getIsSorted() === \"asc\")}>\n        Order\n        <ArrowUpDown />\n      </Button>\n    ),\n    cell: ({ row }) => <div className=\"font-medium\">{row.getValue(\"orderNumber\")}</div>\n  },\n  {\n    id: \"customer\",\n    header: ({ column }) => {\n      return (\n        <Button\n          variant=\"ghost\"\n          onClick={() => column.toggleSorting(column.getIsSorted() === \"asc\")}>\n          Customer\n          <ArrowUpDown />\n        </Button>\n      );\n    },\n    accessorFn: (row) => row.customer.email,\n    cell: ({ row }) => (\n      <div className=\"space-y-0.5\">\n        <div className=\"font-medium\">{row.original.customer.name}</div>\n        <div className=\"text-muted-foreground text-sm lowercase\">{row.original.customer.email}</div>\n      </div>\n    )\n  },\n  {\n    accessorKey: \"status\",\n    header: \"Status\",\n    cell: ({ row }) => <div className=\"capitalize\">{row.getValue(\"status\")}</div>\n  },\n  {\n    id: \"date\",\n    header: \"Date\",\n    accessorFn: (row) => row.createdAt,\n    cell: ({ row }) => <div className=\"text-muted-foreground\">{row.original.createdAt}</div>\n  },\n  {\n    id: \"total\",\n    header: () => <div className=\"text-right\">Total</div>,\n    accessorFn: (row) => row.totals.total,\n    cell: ({ row }) => {\n      const order = row.original;\n      return (\n        <div className=\"text-right font-medium\">\n          {formatCurrency(order.totals.total, order.totals.currency)}\n        </div>\n      );\n    }\n  },\n  {\n    id: \"actions\",\n    enableHiding: false,\n    cell: ({ row }) => {\n      const order = row.original;\n\n      return (\n        <div className=\"text-end\" onClick={(event) => event.stopPropagation()}>\n          <DropdownMenu>\n            <DropdownMenuTrigger asChild>\n              <Button variant=\"ghost\" className=\"h-8 w-8 p-0\">\n                <span className=\"sr-only\">Open menu</span>\n                <MoreHorizontal />\n              </Button>\n            </DropdownMenuTrigger>\n            <DropdownMenuContent align=\"end\">\n              <DropdownMenuLabel>Actions</DropdownMenuLabel>\n              <DropdownMenuItem onClick={() => navigator.clipboard.writeText(order.id)}>\n                Copy order ID\n              </DropdownMenuItem>\n              <DropdownMenuSeparator />\n              <DropdownMenuItem>View order</DropdownMenuItem>\n              <DropdownMenuItem>View customer</DropdownMenuItem>\n            </DropdownMenuContent>\n          </DropdownMenu>\n        </div>\n      );\n    }\n  }\n];\n\nexport default function DataTableDemo() {\n  const [sorting, setSorting] = React.useState<SortingState>([]);\n  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);\n  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});\n  const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({});\n  const [expanded, setExpanded] = React.useState<ExpandedState>({});\n\n  const table = useReactTable({\n    data,\n    columns,\n    onSortingChange: setSorting,\n    onColumnFiltersChange: setColumnFilters,\n    getCoreRowModel: getCoreRowModel(),\n    getPaginationRowModel: getPaginationRowModel(),\n    getSortedRowModel: getSortedRowModel(),\n    getFilteredRowModel: getFilteredRowModel(),\n    onColumnVisibilityChange: setColumnVisibility,\n    onRowSelectionChange: setRowSelection,\n    onExpandedChange: setExpanded,\n    getRowCanExpand: () => true,\n    state: {\n      sorting,\n      columnFilters,\n      columnVisibility,\n      rowSelection,\n      expanded\n    }\n  });\n\n  return (\n    <div className=\"w-full max-w-6xl space-y-4\">\n      <div className=\"flex items-center gap-2\">\n        <InputGroup>\n          <InputGroupInput\n            placeholder=\"Filter orders...\"\n            value={(table.getColumn(\"orderNumber\")?.getFilterValue() as string) ?? \"\"}\n            onChange={(event) => table.getColumn(\"orderNumber\")?.setFilterValue(event.target.value)}\n          />\n          <InputGroupAddon>\n            <SearchIcon />\n          </InputGroupAddon>\n        </InputGroup>\n        <div className=\"ml-auto flex items-center gap-2\">\n          {table.getFilteredSelectedRowModel().rows.length > 0 && (\n            <DropdownMenu>\n              <DropdownMenuTrigger asChild>\n                <Button variant=\"outline\">\n                  Actions\n                  <ChevronDown />\n                </Button>\n              </DropdownMenuTrigger>\n              <DropdownMenuContent align=\"end\">\n                <DropdownMenuLabel>\n                  {table.getFilteredSelectedRowModel().rows.length} selected\n                </DropdownMenuLabel>\n                <DropdownMenuSeparator />\n                <DropdownMenuItem>\n                  <Copy />\n                  Copy selected order IDs\n                </DropdownMenuItem>\n                <DropdownMenuItem>\n                  <FileText />\n                  Copy as JSON\n                </DropdownMenuItem>\n                <DropdownMenuSeparator />\n                <DropdownMenuItem>\n                  <Download />\n                  Export as CSV\n                </DropdownMenuItem>\n                <DropdownMenuSeparator />\n                <DropdownMenuItem className=\"text-destructive focus:text-destructive\">\n                  <Trash2 />\n                  Cancel selected\n                </DropdownMenuItem>\n              </DropdownMenuContent>\n            </DropdownMenu>\n          )}\n          <DropdownMenu>\n            <DropdownMenuTrigger asChild>\n              <Button variant=\"outline\">\n                <ColumnsIcon />\n              </Button>\n            </DropdownMenuTrigger>\n            <DropdownMenuContent align=\"end\">\n              {table\n                .getAllColumns()\n                .filter((column) => column.getCanHide())\n                .map((column) => {\n                  return (\n                    <DropdownMenuCheckboxItem\n                      key={column.id}\n                      className=\"capitalize\"\n                      checked={column.getIsVisible()}\n                      onCheckedChange={(value) => column.toggleVisibility(!!value)}>\n                      {column.id}\n                    </DropdownMenuCheckboxItem>\n                  );\n                })}\n            </DropdownMenuContent>\n          </DropdownMenu>\n        </div>\n      </div>\n      <div className=\"overflow-hidden rounded-md border\">\n        <Table>\n          <TableHeader>\n            {table.getHeaderGroups().map((headerGroup) => (\n              <TableRow key={headerGroup.id}>\n                {headerGroup.headers.map((header) => {\n                  return (\n                    <TableHead key={header.id}>\n                      {header.isPlaceholder\n                        ? null\n                        : flexRender(header.column.columnDef.header, header.getContext())}\n                    </TableHead>\n                  );\n                })}\n              </TableRow>\n            ))}\n          </TableHeader>\n          <TableBody>\n            {table.getRowModel().rows?.length ? (\n              table.getRowModel().rows.map((row) => (\n                <React.Fragment key={row.id}>\n                  <TableRow\n                    data-state={row.getIsSelected() && \"selected\"}\n                    onClick={() => row.toggleExpanded()}\n                    className=\"cursor-pointer\">\n                    {row.getVisibleCells().map((cell) => (\n                      <TableCell key={cell.id}>\n                        {flexRender(cell.column.columnDef.cell, cell.getContext())}\n                      </TableCell>\n                    ))}\n                  </TableRow>\n                  {row.getIsExpanded() && (\n                    <TableRow>\n                      <TableCell colSpan={columns.length} className=\"bg-muted/50\">\n                        <div className=\"space-y-3 py-4\">\n                          <div className=\"text-sm font-semibold\">Order details</div>\n                          <div className=\"grid gap-3 text-sm\">\n                            <div className=\"grid grid-cols-[120px_1fr] gap-2\">\n                              <span className=\"text-muted-foreground\">Order ID</span>\n                              <span className=\"font-medium\">{row.original.id}</span>\n                            </div>\n                            <div className=\"grid grid-cols-[120px_1fr] gap-2\">\n                              <span className=\"text-muted-foreground\">Created</span>\n                              <span>{row.original.createdAt}</span>\n                            </div>\n                            <div className=\"grid grid-cols-[120px_1fr] gap-2\">\n                              <span className=\"text-muted-foreground\">Payment</span>\n                              <span>\n                                {row.original.payment.method}\n                                {row.original.payment.last4\n                                  ? ` •••• ${row.original.payment.last4}`\n                                  : \"\"}\n                                {\" · \"}\n                                <span className=\"capitalize\">{row.original.payment.status}</span>\n                              </span>\n                            </div>\n                            <div className=\"grid grid-cols-[120px_1fr] gap-2\">\n                              <span className=\"text-muted-foreground\">Shipping</span>\n                              <span>\n                                {row.original.shipping.method}\n                                {\" · \"}\n                                {row.original.shipping.address}\n                              </span>\n                            </div>\n                            <div className=\"grid grid-cols-[120px_1fr] gap-2\">\n                              <span className=\"text-muted-foreground\">Items</span>\n                              <div className=\"space-y-2\">\n                                {row.original.items.map((item) => (\n                                  <div\n                                    key={item.sku}\n                                    className=\"flex items-start justify-between gap-4\">\n                                    <div className=\"min-w-0\">\n                                      <div className=\"font-medium\">{item.name}</div>\n                                      <div className=\"text-muted-foreground text-xs\">\n                                        {item.sku}\n                                      </div>\n                                    </div>\n                                    <div className=\"text-right\">\n                                      <div className=\"text-muted-foreground text-xs\">\n                                        Qty {item.quantity}\n                                      </div>\n                                      <div className=\"font-medium\">\n                                        {formatCurrency(\n                                          item.unitPrice * item.quantity,\n                                          row.original.totals.currency\n                                        )}\n                                      </div>\n                                    </div>\n                                  </div>\n                                ))}\n                              </div>\n                            </div>\n                            <div className=\"grid grid-cols-[120px_1fr] gap-2\">\n                              <span className=\"text-muted-foreground\">Totals</span>\n                              <div className=\"space-y-1\">\n                                <div className=\"flex justify-between gap-4\">\n                                  <span className=\"text-muted-foreground\">Subtotal</span>\n                                  <span>\n                                    {formatCurrency(\n                                      row.original.totals.subtotal,\n                                      row.original.totals.currency\n                                    )}\n                                  </span>\n                                </div>\n                                <div className=\"flex justify-between gap-4\">\n                                  <span className=\"text-muted-foreground\">Shipping</span>\n                                  <span>\n                                    {formatCurrency(\n                                      row.original.totals.shipping,\n                                      row.original.totals.currency\n                                    )}\n                                  </span>\n                                </div>\n                                <div className=\"flex justify-between gap-4\">\n                                  <span className=\"text-muted-foreground\">Tax</span>\n                                  <span>\n                                    {formatCurrency(\n                                      row.original.totals.tax,\n                                      row.original.totals.currency\n                                    )}\n                                  </span>\n                                </div>\n                                <div className=\"flex justify-between gap-4 pt-1 font-medium\">\n                                  <span>Total</span>\n                                  <span>\n                                    {formatCurrency(\n                                      row.original.totals.total,\n                                      row.original.totals.currency\n                                    )}\n                                  </span>\n                                </div>\n                              </div>\n                            </div>\n                          </div>\n                        </div>\n                      </TableCell>\n                    </TableRow>\n                  )}\n                </React.Fragment>\n              ))\n            ) : (\n              <TableRow>\n                <TableCell colSpan={columns.length} className=\"h-24 text-center\">\n                  No results.\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        </Table>\n      </div>\n      <div className=\"flex items-center justify-end space-x-2\">\n        <div className=\"text-muted-foreground flex-1 text-sm\">\n          {table.getFilteredSelectedRowModel().rows.length} of{\" \"}\n          {table.getFilteredRowModel().rows.length} row(s) selected.\n        </div>\n        <div className=\"space-x-2\">\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            onClick={() => table.previousPage()}\n            disabled={!table.getCanPreviousPage()}>\n            Previous\n          </Button>\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            onClick={() => table.nextPage()}\n            disabled={!table.getCanNextPage()}>\n            Next\n          </Button>\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/data-table2.tsx"
    }
  ],
  "type": "registry:component"
}