{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-table-03",
  "type": "registry:component",
  "title": "Data Table",
  "author": "Toby Belhome",
  "description": "Display complex data in a table format with filtering, sorting and pagination.",
  "dependencies": [],
  "registryDependencies": [
    "badge",
    "button",
    "checkbox",
    "input",
    "label",
    "pagination",
    "popover"
  ],
  "files": [
    {
      "path": "examples/components/data-table/03/page.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport {\n  ColumnDef,\n  ColumnFiltersState,\n  FilterFn,\n  flexRender,\n  getCoreRowModel,\n  getFacetedUniqueValues,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  PaginationState,\n  Row,\n  SortingState,\n  useReactTable,\n  VisibilityState\n} from \"@tanstack/react-table\";\nimport {\n  ChevronDownIcon,\n  ChevronFirstIcon,\n  ChevronLastIcon,\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  ChevronUpIcon,\n  CircleAlertIcon,\n  CircleXIcon,\n  Columns3Icon,\n  EllipsisIcon,\n  FilterIcon,\n  ListFilterIcon,\n  PlusIcon,\n  TrashIcon\n} from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n  AlertDialog,\n  AlertDialogAction,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger\n} from \"@/components/ui/alert-dialog\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n  DropdownMenu,\n  DropdownMenuCheckboxItem,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuPortal,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuSub,\n  DropdownMenuSubContent,\n  DropdownMenuSubTrigger,\n  DropdownMenuTrigger\n} from \"@/components/ui/dropdown-menu\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Pagination, PaginationContent, PaginationItem } from \"@/components/ui/pagination\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\";\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\";\n\ntype Item = {\n  id: string;\n  name: string;\n  email: string;\n  location: string;\n  flag: string;\n  status: \"Active\" | \"Inactive\" | \"Pending\";\n  balance: number;\n};\n\n// Custom filter function for multi-column searching\nconst multiColumnFilterFn: FilterFn<Item> = (row, columnId, filterValue) => {\n  const searchableRowContent = `${row.original.name} ${row.original.email}`.toLowerCase();\n  const searchTerm = (filterValue ?? \"\").toLowerCase();\n  return searchableRowContent.includes(searchTerm);\n};\n\nconst statusFilterFn: FilterFn<Item> = (row, columnId, filterValue: string[]) => {\n  if (!filterValue?.length) return true;\n  const status = row.getValue(columnId) as string;\n  return filterValue.includes(status);\n};\n\nconst columns: ColumnDef<Item>[] = [\n  {\n    id: \"select\",\n    header: ({ table }) => (\n      <Checkbox\n        checked={\n          table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && \"indeterminate\")\n        }\n        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n        aria-label=\"Select all\"\n      />\n    ),\n    cell: ({ row }) => (\n      <Checkbox\n        checked={row.getIsSelected()}\n        onCheckedChange={(value) => row.toggleSelected(!!value)}\n        aria-label=\"Select row\"\n      />\n    ),\n    size: 28,\n    enableSorting: false,\n    enableHiding: false\n  },\n  {\n    header: \"Name\",\n    accessorKey: \"name\",\n    cell: ({ row }) => <div className=\"font-medium\">{row.getValue(\"name\")}</div>,\n    size: 180,\n    filterFn: multiColumnFilterFn,\n    enableHiding: false\n  },\n  {\n    header: \"Email\",\n    accessorKey: \"email\",\n    size: 220\n  },\n  {\n    header: \"Location\",\n    accessorKey: \"location\",\n    cell: ({ row }) => (\n      <div>\n        <span className=\"text-lg leading-none\">{row.original.flag}</span> {row.getValue(\"location\")}\n      </div>\n    ),\n    size: 180\n  },\n  {\n    header: \"Status\",\n    accessorKey: \"status\",\n    cell: ({ row }) => (\n      <Badge\n        className={cn(\n          row.getValue(\"status\") === \"Inactive\" && \"bg-muted-foreground/60 text-primary-foreground\"\n        )}>\n        {row.getValue(\"status\")}\n      </Badge>\n    ),\n    size: 100,\n    filterFn: statusFilterFn\n  },\n  {\n    header: \"Performance\",\n    accessorKey: \"performance\"\n  },\n  {\n    header: \"Balance\",\n    accessorKey: \"balance\",\n    cell: ({ row }) => {\n      const amount = parseFloat(row.getValue(\"balance\"));\n      const formatted = new Intl.NumberFormat(\"en-US\", {\n        style: \"currency\",\n        currency: \"USD\"\n      }).format(amount);\n      return formatted;\n    },\n    size: 120\n  },\n  {\n    id: \"actions\",\n    header: () => <span className=\"sr-only\">Actions</span>,\n    cell: ({ row }) => <RowActions row={row} />,\n    size: 60,\n    enableHiding: false\n  }\n];\n\nexport default function Component() {\n  const id = useId();\n  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});\n  const [pagination, setPagination] = useState<PaginationState>({\n    pageIndex: 0,\n    pageSize: 10\n  });\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  const [sorting, setSorting] = useState<SortingState>([\n    {\n      id: \"name\",\n      desc: false\n    }\n  ]);\n\n  const [data, setData] = useState<Item[]>([]);\n  useEffect(() => {\n    async function fetchPosts() {\n      const res = await fetch(\n        \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\"\n      );\n      const data = await res.json();\n      setData(data);\n    }\n    fetchPosts();\n  }, []);\n\n  const handleDeleteRows = () => {\n    const selectedRows = table.getSelectedRowModel().rows;\n    const updatedData = data.filter(\n      (item) => !selectedRows.some((row) => row.original.id === item.id)\n    );\n    setData(updatedData);\n    table.resetRowSelection();\n  };\n\n  const table = useReactTable({\n    data,\n    columns,\n    getCoreRowModel: getCoreRowModel(),\n    getSortedRowModel: getSortedRowModel(),\n    onSortingChange: setSorting,\n    enableSortingRemoval: false,\n    getPaginationRowModel: getPaginationRowModel(),\n    onPaginationChange: setPagination,\n    onColumnFiltersChange: setColumnFilters,\n    onColumnVisibilityChange: setColumnVisibility,\n    getFilteredRowModel: getFilteredRowModel(),\n    getFacetedUniqueValues: getFacetedUniqueValues(),\n    state: {\n      sorting,\n      pagination,\n      columnFilters,\n      columnVisibility\n    }\n  });\n\n  // Get unique status values\n  const uniqueStatusValues = useMemo(() => {\n    const statusColumn = table.getColumn(\"status\");\n\n    if (!statusColumn) return [];\n\n    const values = Array.from(statusColumn.getFacetedUniqueValues().keys());\n\n    return values.sort();\n  }, [table.getColumn(\"status\")?.getFacetedUniqueValues()]);\n\n  // Get counts for each status\n  const statusCounts = useMemo(() => {\n    const statusColumn = table.getColumn(\"status\");\n    if (!statusColumn) return new Map();\n    return statusColumn.getFacetedUniqueValues();\n  }, [table.getColumn(\"status\")?.getFacetedUniqueValues()]);\n\n  const selectedStatuses = useMemo(() => {\n    const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n    return filterValue ?? [];\n  }, [table.getColumn(\"status\")?.getFilterValue()]);\n\n  const handleStatusChange = (checked: boolean, value: string) => {\n    const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n    const newFilterValue = filterValue ? [...filterValue] : [];\n\n    if (checked) {\n      newFilterValue.push(value);\n    } else {\n      const index = newFilterValue.indexOf(value);\n      if (index > -1) {\n        newFilterValue.splice(index, 1);\n      }\n    }\n\n    table.getColumn(\"status\")?.setFilterValue(newFilterValue.length ? newFilterValue : undefined);\n  };\n\n  return (\n    <div className=\"space-y-4\">\n      {/* Filters */}\n      <div className=\"flex flex-wrap items-center justify-between gap-3\">\n        <div className=\"flex items-center gap-3\">\n          {/* Filter by name or email */}\n          <div className=\"relative\">\n            <Input\n              id={`${id}-input`}\n              ref={inputRef}\n              className={cn(\n                \"peer min-w-60 ps-9\",\n                Boolean(table.getColumn(\"name\")?.getFilterValue()) && \"pe-9\"\n              )}\n              value={(table.getColumn(\"name\")?.getFilterValue() ?? \"\") as string}\n              onChange={(e) => table.getColumn(\"name\")?.setFilterValue(e.target.value)}\n              placeholder=\"Filter by name or email...\"\n              type=\"text\"\n              aria-label=\"Filter by name or email\"\n            />\n            <div className=\"text-muted-foreground/80 pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 peer-disabled:opacity-50\">\n              <ListFilterIcon size={16} aria-hidden=\"true\" />\n            </div>\n            {Boolean(table.getColumn(\"name\")?.getFilterValue()) && (\n              <button\n                className=\"text-muted-foreground/80 hover:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md transition-[color,box-shadow] outline-none focus:z-10 focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n                aria-label=\"Clear filter\"\n                onClick={() => {\n                  table.getColumn(\"name\")?.setFilterValue(\"\");\n                  if (inputRef.current) {\n                    inputRef.current.focus();\n                  }\n                }}>\n                <CircleXIcon size={16} aria-hidden=\"true\" />\n              </button>\n            )}\n          </div>\n          {/* Filter by status */}\n          <Popover>\n            <PopoverTrigger asChild>\n              <Button variant=\"outline\">\n                <FilterIcon className=\"-ms-1 opacity-60\" size={16} aria-hidden=\"true\" />\n                Status\n                {selectedStatuses.length > 0 && (\n                  <span className=\"bg-background text-muted-foreground/70 -me-1 inline-flex h-5 max-h-full items-center rounded border px-1 font-[inherit] text-[0.625rem] font-medium\">\n                    {selectedStatuses.length}\n                  </span>\n                )}\n              </Button>\n            </PopoverTrigger>\n            <PopoverContent className=\"w-auto min-w-36 p-3\" align=\"start\">\n              <div className=\"space-y-3\">\n                <div className=\"text-muted-foreground text-xs font-medium\">Filters</div>\n                <div className=\"space-y-3\">\n                  {uniqueStatusValues.map((value, i) => (\n                    <div key={value} className=\"flex items-center gap-2\">\n                      <Checkbox\n                        id={`${id}-${i}`}\n                        checked={selectedStatuses.includes(value)}\n                        onCheckedChange={(checked: boolean) => handleStatusChange(checked, value)}\n                      />\n                      <Label\n                        htmlFor={`${id}-${i}`}\n                        className=\"flex grow justify-between gap-2 font-normal\">\n                        {value}{\" \"}\n                        <span className=\"text-muted-foreground ms-2 text-xs\">\n                          {statusCounts.get(value)}\n                        </span>\n                      </Label>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </PopoverContent>\n          </Popover>\n          {/* Toggle columns visibility */}\n          <DropdownMenu>\n            <DropdownMenuTrigger asChild>\n              <Button variant=\"outline\">\n                <Columns3Icon className=\"-ms-1 opacity-60\" size={16} aria-hidden=\"true\" />\n                View\n              </Button>\n            </DropdownMenuTrigger>\n            <DropdownMenuContent align=\"end\">\n              <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>\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                      onSelect={(event) => event.preventDefault()}>\n                      {column.id}\n                    </DropdownMenuCheckboxItem>\n                  );\n                })}\n            </DropdownMenuContent>\n          </DropdownMenu>\n        </div>\n        <div className=\"flex items-center gap-3\">\n          {/* Delete button */}\n          {table.getSelectedRowModel().rows.length > 0 && (\n            <AlertDialog>\n              <AlertDialogTrigger asChild>\n                <Button className=\"ml-auto\" variant=\"outline\">\n                  <TrashIcon className=\"-ms-1 opacity-60\" size={16} aria-hidden=\"true\" />\n                  Delete\n                  <span className=\"bg-background text-muted-foreground/70 -me-1 inline-flex h-5 max-h-full items-center rounded border px-1 font-[inherit] text-[0.625rem] font-medium\">\n                    {table.getSelectedRowModel().rows.length}\n                  </span>\n                </Button>\n              </AlertDialogTrigger>\n              <AlertDialogContent>\n                <div className=\"flex flex-col gap-2 max-sm:items-center sm:flex-row sm:gap-4\">\n                  <div\n                    className=\"flex size-9 shrink-0 items-center justify-center rounded-full border\"\n                    aria-hidden=\"true\">\n                    <CircleAlertIcon className=\"opacity-80\" size={16} />\n                  </div>\n                  <AlertDialogHeader>\n                    <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>\n                    <AlertDialogDescription>\n                      This action cannot be undone. This will permanently delete{\" \"}\n                      {table.getSelectedRowModel().rows.length} selected{\" \"}\n                      {table.getSelectedRowModel().rows.length === 1 ? \"row\" : \"rows\"}.\n                    </AlertDialogDescription>\n                  </AlertDialogHeader>\n                </div>\n                <AlertDialogFooter>\n                  <AlertDialogCancel>Cancel</AlertDialogCancel>\n                  <AlertDialogAction onClick={handleDeleteRows}>Delete</AlertDialogAction>\n                </AlertDialogFooter>\n              </AlertDialogContent>\n            </AlertDialog>\n          )}\n          {/* Add user button */}\n          <Button className=\"ml-auto\" variant=\"outline\">\n            <PlusIcon className=\"-ms-1 opacity-60\" size={16} aria-hidden=\"true\" />\n            Add user\n          </Button>\n        </div>\n      </div>\n\n      {/* Table */}\n      <div className=\"bg-background overflow-hidden rounded-md border\">\n        <Table className=\"table-fixed\">\n          <TableHeader>\n            {table.getHeaderGroups().map((headerGroup) => (\n              <TableRow key={headerGroup.id} className=\"hover:bg-transparent\">\n                {headerGroup.headers.map((header) => {\n                  return (\n                    <TableHead\n                      key={header.id}\n                      style={{ width: `${header.getSize()}px` }}\n                      className=\"h-11\">\n                      {header.isPlaceholder ? null : header.column.getCanSort() ? (\n                        <div\n                          className={cn(\n                            header.column.getCanSort() &&\n                              \"flex h-full cursor-pointer items-center justify-between gap-2 select-none\"\n                          )}\n                          onClick={header.column.getToggleSortingHandler()}\n                          onKeyDown={(e) => {\n                            // Enhanced keyboard handling for sorting\n                            if (\n                              header.column.getCanSort() &&\n                              (e.key === \"Enter\" || e.key === \" \")\n                            ) {\n                              e.preventDefault();\n                              header.column.getToggleSortingHandler()?.(e);\n                            }\n                          }}\n                          tabIndex={header.column.getCanSort() ? 0 : undefined}>\n                          {flexRender(header.column.columnDef.header, header.getContext())}\n                          {{\n                            asc: (\n                              <ChevronUpIcon\n                                className=\"shrink-0 opacity-60\"\n                                size={16}\n                                aria-hidden=\"true\"\n                              />\n                            ),\n                            desc: (\n                              <ChevronDownIcon\n                                className=\"shrink-0 opacity-60\"\n                                size={16}\n                                aria-hidden=\"true\"\n                              />\n                            )\n                          }[header.column.getIsSorted() as string] ?? null}\n                        </div>\n                      ) : (\n                        flexRender(header.column.columnDef.header, header.getContext())\n                      )}\n                    </TableHead>\n                  );\n                })}\n              </TableRow>\n            ))}\n          </TableHeader>\n          <TableBody>\n            {table.getRowModel().rows?.length ? (\n              table.getRowModel().rows.map((row) => (\n                <TableRow key={row.id} data-state={row.getIsSelected() && \"selected\"}>\n                  {row.getVisibleCells().map((cell) => (\n                    <TableCell key={cell.id} className=\"last:py-0\">\n                      {flexRender(cell.column.columnDef.cell, cell.getContext())}\n                    </TableCell>\n                  ))}\n                </TableRow>\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\n      {/* Pagination */}\n      <div className=\"flex items-center justify-between gap-8\">\n        {/* Results per page */}\n        <div className=\"flex items-center gap-3\">\n          <Label htmlFor={id} className=\"max-sm:sr-only\">\n            Rows per page\n          </Label>\n          <Select\n            value={table.getState().pagination.pageSize.toString()}\n            onValueChange={(value) => {\n              table.setPageSize(Number(value));\n            }}>\n            <SelectTrigger id={id} className=\"w-fit whitespace-nowrap\">\n              <SelectValue placeholder=\"Select number of results\" />\n            </SelectTrigger>\n            <SelectContent className=\"[&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8 [&_*[role=option]>span]:start-auto [&_*[role=option]>span]:end-2\">\n              {[5, 10, 25, 50].map((pageSize) => (\n                <SelectItem key={pageSize} value={pageSize.toString()}>\n                  {pageSize}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n        </div>\n        {/* Page number information */}\n        <div className=\"text-muted-foreground flex grow justify-end text-sm whitespace-nowrap\">\n          <p className=\"text-muted-foreground text-sm whitespace-nowrap\" aria-live=\"polite\">\n            <span className=\"text-foreground\">\n              {table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}-\n              {Math.min(\n                Math.max(\n                  table.getState().pagination.pageIndex * table.getState().pagination.pageSize +\n                    table.getState().pagination.pageSize,\n                  0\n                ),\n                table.getRowCount()\n              )}\n            </span>{\" \"}\n            of <span className=\"text-foreground\">{table.getRowCount().toString()}</span>\n          </p>\n        </div>\n\n        {/* Pagination buttons */}\n        <div>\n          <Pagination>\n            <PaginationContent>\n              {/* First page button */}\n              <PaginationItem>\n                <Button\n                  size=\"icon\"\n                  variant=\"outline\"\n                  className=\"disabled:pointer-events-none disabled:opacity-50\"\n                  onClick={() => table.firstPage()}\n                  disabled={!table.getCanPreviousPage()}\n                  aria-label=\"Go to first page\">\n                  <ChevronFirstIcon size={16} aria-hidden=\"true\" />\n                </Button>\n              </PaginationItem>\n              {/* Previous page button */}\n              <PaginationItem>\n                <Button\n                  size=\"icon\"\n                  variant=\"outline\"\n                  className=\"disabled:pointer-events-none disabled:opacity-50\"\n                  onClick={() => table.previousPage()}\n                  disabled={!table.getCanPreviousPage()}\n                  aria-label=\"Go to previous page\">\n                  <ChevronLeftIcon size={16} aria-hidden=\"true\" />\n                </Button>\n              </PaginationItem>\n              {/* Next page button */}\n              <PaginationItem>\n                <Button\n                  size=\"icon\"\n                  variant=\"outline\"\n                  className=\"disabled:pointer-events-none disabled:opacity-50\"\n                  onClick={() => table.nextPage()}\n                  disabled={!table.getCanNextPage()}\n                  aria-label=\"Go to next page\">\n                  <ChevronRightIcon size={16} aria-hidden=\"true\" />\n                </Button>\n              </PaginationItem>\n              {/* Last page button */}\n              <PaginationItem>\n                <Button\n                  size=\"icon\"\n                  variant=\"outline\"\n                  className=\"disabled:pointer-events-none disabled:opacity-50\"\n                  onClick={() => table.lastPage()}\n                  disabled={!table.getCanNextPage()}\n                  aria-label=\"Go to last page\">\n                  <ChevronLastIcon size={16} aria-hidden=\"true\" />\n                </Button>\n              </PaginationItem>\n            </PaginationContent>\n          </Pagination>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nfunction RowActions({ row }: { row: Row<Item> }) {\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger asChild>\n        <div className=\"flex justify-end\">\n          <Button size=\"icon\" variant=\"ghost\" className=\"shadow-none\" aria-label=\"Edit item\">\n            <EllipsisIcon size={16} aria-hidden=\"true\" />\n          </Button>\n        </div>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\">\n        <DropdownMenuGroup>\n          <DropdownMenuItem>\n            <span>Edit</span>\n            <DropdownMenuShortcut>⌘E</DropdownMenuShortcut>\n          </DropdownMenuItem>\n          <DropdownMenuItem>\n            <span>Duplicate</span>\n            <DropdownMenuShortcut>⌘D</DropdownMenuShortcut>\n          </DropdownMenuItem>\n        </DropdownMenuGroup>\n        <DropdownMenuSeparator />\n        <DropdownMenuGroup>\n          <DropdownMenuItem>\n            <span>Archive</span>\n            <DropdownMenuShortcut>⌘A</DropdownMenuShortcut>\n          </DropdownMenuItem>\n          <DropdownMenuSub>\n            <DropdownMenuSubTrigger>More</DropdownMenuSubTrigger>\n            <DropdownMenuPortal>\n              <DropdownMenuSubContent>\n                <DropdownMenuItem>Move to project</DropdownMenuItem>\n                <DropdownMenuItem>Move to folder</DropdownMenuItem>\n                <DropdownMenuSeparator />\n                <DropdownMenuItem>Advanced options</DropdownMenuItem>\n              </DropdownMenuSubContent>\n            </DropdownMenuPortal>\n          </DropdownMenuSub>\n        </DropdownMenuGroup>\n        <DropdownMenuSeparator />\n        <DropdownMenuGroup>\n          <DropdownMenuItem>Share</DropdownMenuItem>\n          <DropdownMenuItem>Add to favorites</DropdownMenuItem>\n        </DropdownMenuGroup>\n        <DropdownMenuSeparator />\n        <DropdownMenuItem className=\"text-destructive focus:text-destructive\">\n          <span>Delete</span>\n          <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/data-table-03.tsx"
    }
  ],
  "meta": {
    "isPro": false
  }
}