{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "table",
  "title": "Table",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-angular/components/table/table.component.ts",
      "content": "import { Component, Input, ChangeDetectionStrategy } from '@angular/core'\nimport { cn } from '@/lib/utils'\n\nexport type TableDensity = 'compact' | 'cozy' | 'comfortable'\n\nexport function tableDensityClass(density: TableDensity): string {\n  if (density === 'compact') return '[&_td]:py-1.5 [&_td]:text-xs [&_th]:h-8 [&_th]:text-xs'\n  if (density === 'comfortable') return '[&_td]:py-3 [&_th]:h-12'\n  return ''\n}\n\n/**\n * Angular port of UIPKGE Table — plain table primitives with registry\n * borders/padding/tokens. Same parts as Vue (Table, Header, Body, Footer,\n * Row, Head, Cell, Caption, Empty) and same density scale. The scroll\n * container lives on the host so sticky headers keep working.\n *\n * The root `<ui-table>` element form is safe: it renders its own wrapper\n * (the host) plus the inner `<table>`, so nothing custom sits inside a\n * table in the SSR HTML.\n *\n * DEPRECATED — element forms of the parts that live INSIDE the table:\n * `<ui-table-header>`, `<ui-table-body>`, `<ui-table-footer>`,\n * `<ui-table-row>`, `<ui-table-head>`, `<ui-table-cell>`, `<ui-table-caption>`.\n * When the browser parses SSR HTML, any unknown element inside `<table>`\n * is foster-parented out of the table, so hydration finds a broken table.\n * They still work for client-only rendering and are kept so existing\n * consumers don't break, but use the native element + attribute form:\n *\n *   <ui-table>\n *     <caption ui-table-caption>…</caption>\n *     <thead ui-table-header><tr ui-table-row><th ui-table-head>…</th></tr></thead>\n *     <tbody ui-table-body><tr ui-table-row><td ui-table-cell>…</td></tr></tbody>\n *     <tfoot ui-table-footer><tr ui-table-row><td ui-table-cell>…</td></tr></tfoot>\n *   </ui-table>\n *\n * (Not tagged `@deprecated`: the attribute form shares the same class, so\n * the tag would wrongly flag the recommended usage too.)\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-table, [ui-table]',\n  standalone: true,\n  host: {\n    '[attr.data-slot]': '\"table-container\"',\n    '[attr.data-uipkge]': '\"\"',\n    '[class]': 'hostClass',\n  },\n  template: `<table data-uipkge data-slot=\"table\" [class]=\"tableClass\">\n    <ng-content />\n  </table>`,\n})\nexport class UiTableComponent {\n  @Input('class') className?: string\n  @Input() containerClass?: string\n  @Input() density: TableDensity = 'cozy'\n\n  get hostClass(): string {\n    return cn('block relative w-full overflow-auto', this.containerClass)\n  }\n\n  get tableClass(): string {\n    return cn('w-full caption-bottom text-sm', tableDensityClass(this.density), this.className)\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-header, [ui-table-header]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-header\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableHeaderComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn('table-header-group bg-muted/50 [&_tr]:border-b', this.className)\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-body, [ui-table-body]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-body\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableBodyComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn('table-row-group [&_tr:last-child]:border-0', this.className)\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-footer, [ui-table-footer]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-footer\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableFooterComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn('table-footer-group bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', this.className)\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-row, [ui-table-row]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-row\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableRowComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn(\n      'table-row hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors duration-150',\n      this.className,\n    )\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-head, [ui-table-head]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-head\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableHeadComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn(\n      'table-cell text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n      this.className,\n    )\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-cell, [ui-table-cell]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-cell\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableCellComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn(\n      'table-cell px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n      this.className,\n    )\n  }\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  // Element form deprecated (SSR foster-parenting) — see the note on UiTableComponent.\n  selector: 'ui-table-caption, [ui-table-caption]',\n  standalone: true,\n  host: { '[attr.data-slot]': '\"table-caption\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<ng-content />`,\n})\nexport class UiTableCaptionComponent {\n  @Input('class') className?: string\n  get hostClass(): string {\n    return cn('table-caption text-muted-foreground mt-4 text-sm', this.className)\n  }\n}\n\n/**\n * Empty-state row. Attribute selector on a native <tr> ON PURPOSE: a custom\n * <ui-table-empty> element inside <table>/<tbody> is foster-parented out of\n * the table by the HTML parser when the browser parses SSR HTML, so\n * hydration finds an empty table and crashes. The same applies to every\n * table part — always use <thead ui-table-header>, <tbody ui-table-body>,\n * <tr ui-table-row>, <th ui-table-head> and <td ui-table-cell>, never the\n * element form, inside a table.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'tr[ui-table-empty]',\n  standalone: true,\n  imports: [UiTableCellComponent],\n  host: { '[attr.data-slot]': '\"table-empty\"', '[attr.data-uipkge]': '\"\"', '[class]': 'hostClass' },\n  template: `<td ui-table-cell [attr.colspan]=\"colSpan\" [class]=\"cellClass\"><div class=\"flex items-center justify-center py-10\"><ng-content /></div></td>`,\n})\nexport class UiTableEmptyComponent {\n  @Input() colSpan = 1\n  @Input('class') className?: string\n  get hostClass(): string {\n    // The host IS the row (React renders a TableRow root), so it carries the\n    // row classes directly — no wrapper element inside the tbody.\n    return cn(\n      'table-row hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors duration-150',\n      this.className,\n    )\n  }\n  get cellClass(): string {\n    return 'text-foreground p-4 align-middle text-sm whitespace-nowrap'\n  }\n}\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/table/table.component.ts"
    },
    {
      "path": "packages/registry-angular/components/table/index.ts",
      "content": "export {\n  UiTableComponent,\n  UiTableHeaderComponent,\n  UiTableBodyComponent,\n  UiTableFooterComponent,\n  UiTableRowComponent,\n  UiTableHeadComponent,\n  UiTableCellComponent,\n  UiTableCaptionComponent,\n  UiTableEmptyComponent,\n  tableDensityClass,\n  type TableDensity,\n} from './table.component'\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/table/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Plain HTML table primitives — Table, Header, Row, Cell — with the registry borders, padding, and tokens applied. Use this when Data Table is too heavy.",
  "categories": [
    "data-display"
  ]
}