{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table",
  "title": "Table",
  "dependencies": [
    "@phosphor-icons/react"
  ],
  "registryDependencies": [
    "https://ui.hotfix.jobs/r/recipes.json",
    "https://ui.hotfix.jobs/r/tokens.json",
    "https://ui.hotfix.jobs/r/utils.json"
  ],
  "files": [
    {
      "path": "registry/components/ui/table.tsx",
      "content": "\"use client\";\n\nimport { CaretDown, CaretUp, CaretUpDown } from \"@phosphor-icons/react/dist/ssr\";\nimport { createContext, useContext } from \"react\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { selectionFocus } from \"@/lib/recipes\";\n\n/** Semantic HTML table with horizontal row dividers by default. */\ntype TableSize = \"sm\" | \"md\";\n\ninterface TableContextValue {\n  size: TableSize;\n  interactive: boolean;\n}\n\nconst TableContext = createContext<TableContextValue>({\n  size: \"md\",\n  interactive: false,\n});\n\nexport interface TableProps\n  extends React.TableHTMLAttributes<HTMLTableElement> {\n  /** Adds a layer background, rounded corners, and an outer hairline. */\n  bordered?: boolean;\n  /** Row density. `md` default; `sm` tightens for dense grids. */\n  size?: TableSize;\n  /** Row hover effect (opt in for actionable rows). */\n  interactive?: boolean;\n  /** Wrap in a horizontally-scrollable container. Default true. */\n  scrollable?: boolean;\n  /** Pin the header row to the top of the scroll container. Consumer\n   *  must give the container a fixed height (e.g. via className) for\n   *  vertical sticky to have room to work. */\n  stickyHeader?: boolean;\n}\n\nexport function Table({\n  className,\n  bordered = false,\n  size = \"md\",\n  interactive = false,\n  scrollable = true,\n  stickyHeader = false,\n  ...props\n}: TableProps): React.ReactElement {\n  const ctx: TableContextValue = { size, interactive };\n  const tableEl = (\n    <TableContext.Provider value={ctx}>\n      <table\n        data-slot=\"table\"\n        data-bordered={bordered || undefined}\n        data-size={size}\n        className={cn(\n          \"w-full caption-bottom border-separate border-spacing-0 text-small text-ink\",\n          stickyHeader && \"[&_thead>tr>th]:sticky [&_thead>tr>th]:top-0 [&_thead>tr>th]:z-10 [&_thead>tr>th]:bg-layer-1\",\n          className,\n        )}\n        {...props}\n      />\n    </TableContext.Provider>\n  );\n\n  if (bordered) {\n    return (\n      <div\n        data-slot=\"table-container\"\n        className={cn(\n          \"relative w-full overflow-hidden rounded-[var(--radius-12)] bg-layer-1 border border-hairline\",\n          scrollable && \"overflow-x-auto\",\n        )}\n      >\n        {tableEl}\n      </div>\n    );\n  }\n\n  if (!scrollable) return tableEl;\n  return (\n    <div\n      data-slot=\"table-container\"\n      className=\"relative w-full overflow-x-auto\"\n    >\n      {tableEl}\n    </div>\n  );\n}\n\n/* ------------------------------ Sections ----------------------------- */\n\nexport type TableSectionProps = React.HTMLAttributes<HTMLTableSectionElement>;\n\nexport function TableHeader({\n  className,\n  ...props\n}: TableSectionProps): React.ReactElement {\n  return (\n    <thead\n      data-slot=\"table-header\"\n      className={cn(className)}\n      {...props}\n    />\n  );\n}\n\nexport function TableBody({\n  className,\n  ...props\n}: TableSectionProps): React.ReactElement {\n  const { interactive } = useContext(TableContext);\n  return (\n    <tbody\n      data-slot=\"table-body\"\n      data-interactive={interactive ? \"\" : undefined}\n      className={cn(\n        \"[&_td]:border-b [&_td]:border-hairline-soft [&_tr:last-child>td]:border-b-0\",\n        interactive && [\n          \"[&_tr:hover>td]:bg-layer-hover\",\n          \"[&_tr[data-selected]:hover>td]:bg-layer-hover\",\n        ],\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport function TableFooter({\n  className,\n  ...props\n}: TableSectionProps): React.ReactElement {\n  return (\n    <tfoot\n      data-slot=\"table-footer\"\n      className={cn(\n        \"font-medium\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\n/* -------------------------------- Rows ------------------------------- */\n\nexport interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {\n  /** Marks the row as selected and sets `aria-selected`. */\n  selected?: boolean;\n}\n\nexport function TableRow({\n  className,\n  selected,\n  ...props\n}: TableRowProps): React.ReactElement {\n  return (\n    <tr\n      data-slot=\"table-row\"\n      data-selected={selected || undefined}\n      aria-selected={selected || undefined}\n      className={cn(\n        selected && \"[&>td]:bg-layer-hover\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\n/* -------------------------------- Cells ------------------------------ */\n\nconst headHeightBySize: Record<TableSize, string> = {\n  sm: \"h-7 py-1\",\n  md: \"h-9 py-2\",\n};\n\nconst cellPadBySize: Record<TableSize, string> = {\n  sm: \"px-3 py-1.5\",\n  md: \"px-3 py-2.5\",\n};\n\ntype SortDirection = \"asc\" | \"desc\" | \"none\";\n\nexport interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {\n  /** Text alignment for the header cell content. */\n  align?: \"left\" | \"center\" | \"right\";\n}\n\nexport function TableHead({\n  className,\n  align = \"left\",\n  ...props\n}: TableHeadProps): React.ReactElement {\n  const { size } = useContext(TableContext);\n\n  return (\n    <th\n      data-slot=\"table-head\"\n      className={cn(\n        headHeightBySize[size],\n        \"border-b border-hairline-strong px-3 text-mini font-medium text-ink-muted whitespace-nowrap\",\n        align === \"right\" && \"text-right\",\n        align === \"center\" && \"text-center\",\n        align === \"left\" && \"text-left\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport interface TableSortButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n  direction?: SortDirection;\n}\n\n/** Compact sort control composed inside a TableHead. */\nexport function TableSortButton({\n  className,\n  direction = \"none\",\n  children,\n  ...props\n}: TableSortButtonProps): React.ReactElement {\n  return (\n    <button\n      type=\"button\"\n      data-slot=\"table-sort-button\"\n      data-direction={direction}\n      className={cn(\n        \"-mx-1 inline-flex h-7 items-center gap-1 rounded-[var(--radius-6)] px-1 text-mini font-medium text-ink-muted hover:bg-layer-hover hover:text-ink focus-visible:bg-layer-hover active:bg-layer-hover transition-colors duration-[var(--duration-state)] ease-[var(--ease-standard)]\",\n        direction !== \"none\" && \"text-ink\",\n        selectionFocus,\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      {direction === \"asc\" ? (\n        <CaretUp aria-hidden className=\"size-3 shrink-0\" />\n      ) : direction === \"desc\" ? (\n        <CaretDown aria-hidden className=\"size-3 shrink-0\" />\n      ) : (\n        <CaretUpDown aria-hidden className=\"size-3 shrink-0 opacity-60\" />\n      )}\n    </button>\n  );\n}\n\nexport interface TableCellProps\n  extends React.TdHTMLAttributes<HTMLTableCellElement> {\n  align?: \"left\" | \"center\" | \"right\";\n}\n\nexport function TableCell({\n  className,\n  align = \"left\",\n  ...props\n}: TableCellProps): React.ReactElement {\n  const { size } = useContext(TableContext);\n  return (\n    <td\n      data-slot=\"table-cell\"\n      className={cn(\n        cellPadBySize[size],\n        \"align-middle\",\n        align === \"right\" && \"text-right tabular-nums\",\n        align === \"center\" && \"text-center\",\n        align === \"left\" && \"text-left\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\n/* ------------------------------ Caption ------------------------------ */\n\nexport type TableCaptionProps = React.HTMLAttributes<HTMLTableCaptionElement>;\n\nexport function TableCaption({\n  className,\n  ...props\n}: TableCaptionProps): React.ReactElement {\n  return (\n    <caption\n      data-slot=\"table-caption\"\n      className={cn(\"mt-3 text-mini text-ink-muted text-left\", className)}\n      {...props}\n    />\n  );\n}\n\n/* -------------------------------- Empty ------------------------------ */\n\nexport type TableEmptyProps = React.HTMLAttributes<HTMLTableCellElement> & {\n  /** Number of columns to span across. Required so the cell fills the\n   *  full table width. */\n  colSpan: number;\n};\n\n/** Render an empty-state row inside `<TableBody>`. Wrap `<EmptyState>`\n *  or any custom content; the cell centers it and spans the full width. */\nexport function TableEmpty({\n  className,\n  children,\n  colSpan,\n  ...props\n}: TableEmptyProps): React.ReactElement {\n  return (\n    <tr data-slot=\"table-empty\">\n      <td\n        colSpan={colSpan}\n        className={cn(\n          \"px-3 py-10 text-center align-middle text-small text-ink-muted\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n      </td>\n    </tr>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/ui/table.tsx"
    }
  ],
  "type": "registry:ui"
}