{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table",
  "title": "Table",
  "description": "A data table on native table elements, with a scroll container, selected rows and sortable column headers.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@corsair-ui/utils"
  ],
  "files": [
    {
      "path": "registry/default/ui/table.tsx",
      "content": "import { ArrowDownIcon, ArrowUpIcon, ChevronsUpDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\ntype TableSortDirection = \"asc\" | \"desc\" | false;\ninterface TableProps extends ComponentProps<\"table\"> {\n  /**\n   * Names the scroll container and makes it a focusable region, so keyboard\n   * users can scroll a table that is wider than its box. Set it whenever the\n   * content can overflow.\n   */\n  scrollLabel?: string;\n}\n/**\n * A data table built on the native table elements, so screen readers get\n * rows, columns and headers for free. It sits in a container that scrolls\n * sideways when the table is too wide. When that can happen, pass\n * `scrollLabel`: the container becomes a named region with `tabIndex={0}`,\n * so it can be reached with Tab and scrolled with the arrow keys. Rows show\n * `data-state=\"selected\"` in a muted colour. For sortable columns, put a\n * `TableSortButton` in the `TableHead` and pass the same direction to the\n * head's `sort` prop, which sets `aria-sort`. Nothing animates beyond a\n * colour change on hover.\n *\n * @example\n * <Table scrollLabel=\"Invoices\">\n *   <TableCaption>Invoices from the last 30 days.</TableCaption>\n *   <TableHeader>\n *     <TableRow>\n *       <TableHead sort={sort}>\n *         <TableSortButton direction={sort} onSort={setSort}>Amount</TableSortButton>\n *       </TableHead>\n *       <TableHead>Status</TableHead>\n *     </TableRow>\n *   </TableHeader>\n *   <TableBody>\n *     <TableRow>\n *       <TableCell>{amount}</TableCell>\n *       <TableCell>Paid</TableCell>\n *     </TableRow>\n *   </TableBody>\n * </Table>\n */\nfunction Table({ className, scrollLabel, ...props }: TableProps) {\n  return (\n    <div\n      data-slot=\"table-container\"\n      role={scrollLabel ? \"region\" : undefined}\n      aria-label={scrollLabel}\n      // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- a scrolling region has to be reachable from the keyboard (WCAG 2.1.1)\n      tabIndex={scrollLabel ? 0 : undefined}\n      className={cn(\n        \"relative w-full overflow-x-auto rounded-md outline-none\",\n        \"focus-visible:ring-ring/50 focus-visible:ring-[3px]\"\n      )}\n    >\n      <table\n        data-slot=\"table\"\n        className={cn(\"w-full caption-bottom text-sm\", className)}\n        {...props}\n      />\n    </div>\n  );\n}\nfunction TableHeader({ className, ...props }: ComponentProps<\"thead\">) {\n  return <thead data-slot=\"table-header\" className={cn(\"[&_tr]:border-b\", className)} {...props} />;\n}\nfunction TableBody({ className, ...props }: ComponentProps<\"tbody\">) {\n  return (\n    <tbody\n      data-slot=\"table-body\"\n      className={cn(\"[&_tr:last-child]:border-0\", className)}\n      {...props}\n    />\n  );\n}\nfunction TableFooter({ className, ...props }: ComponentProps<\"tfoot\">) {\n  return (\n    <tfoot\n      data-slot=\"table-footer\"\n      className={cn(\"bg-muted/50 border-t font-medium\", className)}\n      {...props}\n    />\n  );\n}\n/** A row. Set `data-state=\"selected\"` on selected rows (and say so in a cell, a checkbox for example). */\nfunction TableRow({ className, ...props }: ComponentProps<\"tr\">) {\n  return (\n    <tr\n      data-slot=\"table-row\"\n      className={cn(\n        \"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors motion-reduce:transition-none\",\n        className\n      )}\n      {...props}\n    />\n  );\n}\nconst ARIA_SORT = { asc: \"ascending\", desc: \"descending\" } as const;\ninterface TableHeadProps extends ComponentProps<\"th\"> {\n  /** The column's sort direction. Sets `aria-sort` (\"ascending\", \"descending\" or \"none\"); leave it out on columns that do not sort. */\n  sort?: TableSortDirection;\n}\n/** A column header cell. */\nfunction TableHead({ className, sort, ...props }: TableHeadProps) {\n  return (\n    <th\n      data-slot=\"table-head\"\n      aria-sort={sort === undefined ? undefined : sort ? ARIA_SORT[sort] : \"none\"}\n      className={cn(\n        \"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap\",\n        \"[&:has([role=checkbox])]:pr-0\",\n        className\n      )}\n      {...props}\n    />\n  );\n}\nfunction TableCell({ className, ...props }: ComponentProps<\"td\">) {\n  return (\n    <td\n      data-slot=\"table-cell\"\n      className={cn(\"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\", className)}\n      {...props}\n    />\n  );\n}\n/** Describes the table; screen readers read it as the table's name. */\nfunction TableCaption({ className, ...props }: ComponentProps<\"caption\">) {\n  return (\n    <caption\n      data-slot=\"table-caption\"\n      className={cn(\"text-muted-foreground mt-4 text-sm\", className)}\n      {...props}\n    />\n  );\n}\ninterface TableSortButtonProps extends ComponentProps<\"button\"> {\n  /** The column's current sort direction, or `false` when it is not sorted. */\n  direction?: TableSortDirection;\n  /** Called on click with the direction that would come next: \"asc\" unless it already is, then \"desc\". */\n  onSort?: (next: \"asc\" | \"desc\") => void;\n}\n/**\n * The button in a sortable column header. It shows an up or down arrow for\n * the current direction, or a neutral mark when the column is not sorted,\n * and exposes the direction as `data-direction`. The arrows are hidden from\n * screen readers: they hear the column's `aria-sort`, so pass the same\n * direction to the surrounding `TableHead`'s `sort` prop.\n */\nfunction TableSortButton({\n  direction = false,\n  onSort,\n  onClick,\n  className,\n  children,\n  ...props\n}: TableSortButtonProps) {\n  const Icon =\n    direction === \"asc\" ? ArrowUpIcon : direction === \"desc\" ? ArrowDownIcon : ChevronsUpDownIcon;\n  return (\n    <button\n      type=\"button\"\n      data-slot=\"table-sort-button\"\n      data-direction={direction || \"none\"}\n      onClick={(event) => {\n        onClick?.(event);\n        if (!event.defaultPrevented) onSort?.(direction === \"asc\" ? \"desc\" : \"asc\");\n      }}\n      className={cn(\n        \"-ml-2 inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md px-2 font-medium\",\n        \"hover:bg-accent hover:text-accent-foreground\",\n        \"transition-[color,background-color,box-shadow] outline-none motion-reduce:transition-none\",\n        \"focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n        \"disabled:pointer-events-none disabled:opacity-50\",\n        \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n      <Icon\n        aria-hidden=\"true\"\n        data-slot=\"table-sort-icon\"\n        className={cn(!direction && \"text-muted-foreground\")}\n      />\n    </button>\n  );\n}\nexport {\n  Table,\n  TableBody,\n  TableCaption,\n  TableCell,\n  TableFooter,\n  TableHead,\n  TableHeader,\n  TableRow,\n  TableSortButton,\n  type TableHeadProps,\n  type TableProps,\n  type TableSortButtonProps,\n  type TableSortDirection,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}