{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "table-layout",
  "title": "Layout table",
  "description": "Styled table: the Layout set. 5 decorative table variations (StickyHeaderTable, ScrollTable, FixedTable, WideTable, DenseTable) on the ai2 token system, driven by CSS token transitions and sized sm to xl. Part of the free styled layer.",
  "dependencies": [],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/table-layout.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Layout table family: 5 layout treatments. A sticky header, a scrolling body, fixed\n   column widths (table-fixed + truncation), a wide data set (a sticky first column)\n   and dense rows. Color comes ONLY from semantic tokens, via alpha color-mix. No\n   animation, pure CSS; deterministic and renders with no props too. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\ntype Column = { key: string; label: React.ReactNode }\ntype Row = Record<string, React.ReactNode>\n\ntype TableProps = {\n  className?: string\n  size?: StyledSize\n  columns?: Column[]\n  rows?: Row[]\n}\n\n/* A sensible default data set so it renders without props. */\nconst defaultColumns: Column[] = [\n  { key: \"name\", label: \"Name\" },\n  { key: \"role\", label: \"Role\" },\n  { key: \"status\", label: \"Status\" },\n]\n\nconst defaultRows: Row[] = [\n  { name: \"Ada Lovelace\", role: \"Engineer\", status: \"Active\" },\n  { name: \"Alan Turing\", role: \"Researcher\", status: \"Active\" },\n  { name: \"Grace Hopper\", role: \"Architect\", status: \"Away\" },\n  { name: \"Katherine Johnson\", role: \"Analyst\", status: \"Active\" },\n]\n\n/* A longer, deterministic list for the scrolling variants. */\nconst longRows: Row[] = defaultRows.concat(\n  defaultRows.map((r) => ({ ...r, name: `${String(r.name)} II` })),\n  defaultRows.map((r) => ({ ...r, name: `${String(r.name)} III` })),\n  defaultRows.map((r) => ({ ...r, name: `${String(r.name)} IV` }))\n)\n\n/* A multi-column data set for the wide variant. */\nconst wideColumns: Column[] = [\n  { key: \"name\", label: \"Name\" },\n  { key: \"role\", label: \"Role\" },\n  { key: \"team\", label: \"Team\" },\n  { key: \"location\", label: \"Location\" },\n  { key: \"started\", label: \"Started\" },\n  { key: \"email\", label: \"Email\" },\n  { key: \"status\", label: \"Status\" },\n]\n\nconst wideRows: Row[] = [\n  { name: \"Ada Lovelace\", role: \"Engineer\", team: \"Platform\", location: \"London\", started: \"2019\", email: \"ada@example.com\", status: \"Active\" },\n  { name: \"Alan Turing\", role: \"Researcher\", team: \"Research\", location: \"Manchester\", started: \"2020\", email: \"alan@example.com\", status: \"Active\" },\n  { name: \"Grace Hopper\", role: \"Architect\", team: \"Core\", location: \"New York\", started: \"2018\", email: \"grace@example.com\", status: \"Away\" },\n  { name: \"Katherine Johnson\", role: \"Analyst\", team: \"Data\", location: \"Hampton\", started: \"2021\", email: \"katherine@example.com\", status: \"Active\" },\n]\n\n/* A long-text data set for the fixed-width variant (so the clipping is visible). */\nconst fixedRows: Row[] = [\n  { name: \"Ada Lovelace\", role: \"Principal engineer, compiler and runtime platform\", status: \"Active\" },\n  { name: \"Alan Turing\", role: \"Researcher, computability and machine intelligence\", status: \"Active\" },\n  { name: \"Grace Hopper\", role: \"Architect, distributed systems and tooling\", status: \"Away\" },\n  { name: \"Katherine Johnson\", role: \"Analyst, orbital mechanics and trajectory review\", status: \"Active\" },\n]\n\n/* Hucre yogunlugu: padding + metin olcegi. */\nconst cell: Record<StyledSize, string> = {\n  sm: \"px-2.5 py-1.5 text-xs\",\n  md: \"px-3 py-2 text-sm\",\n  lg: \"px-4 py-2.5 text-sm\",\n  xl: \"px-5 py-3 text-base\",\n}\n\nconst headCell: Record<StyledSize, string> = {\n  sm: \"px-2.5 py-1.5 text-xs\",\n  md: \"px-3 py-2 text-xs\",\n  lg: \"px-4 py-2.5 text-sm\",\n  xl: \"px-5 py-3 text-sm\",\n}\n\n/* An even tighter scale for the dense variant. */\nconst denseCell: Record<StyledSize, string> = {\n  sm: \"px-2 py-0.5 text-xs\",\n  md: \"px-2 py-1 text-xs\",\n  lg: \"px-2.5 py-1 text-sm\",\n  xl: \"px-3 py-1.5 text-sm\",\n}\n\nconst tableBase = \"w-full border-collapse text-left align-middle text-foreground\"\nconst headBase = \"font-medium text-muted-foreground\"\n\nfunction resolve(columns: Column[] | undefined, rows: Row[] | undefined, fbCols: Column[], fbRows: Row[]) {\n  return {\n    cols: columns && columns.length > 0 ? columns : fbCols,\n    data: rows && rows.length > 0 ? rows : fbRows,\n  }\n}\n\n/* StickyHeader: the header stays pinned to the top edge while the body scrolls vertically. */\nexport function StickyHeaderTable({ className, size = \"md\", columns, rows }: TableProps) {\n  const { cols, data } = resolve(columns, rows, defaultColumns, longRows)\n  return (\n    <div\n      data-slot=\"styled-table\"\n      className={cn(\"max-h-64 w-full overflow-auto rounded-lg border border-border\", className)}\n    >\n      <table className={tableBase}>\n        <thead className=\"sticky top-0 z-10\">\n          <tr>\n            {cols.map((col) => (\n              <th\n                key={col.key}\n                scope=\"col\"\n                className={cn(headBase, headCell[size], \"border-b border-border bg-muted\")}\n              >\n                {col.label}\n              </th>\n            ))}\n          </tr>\n        </thead>\n        <tbody>\n          {data.map((row, i) => (\n            <tr key={i} className=\"border-b border-border/60 last:border-b-0\">\n              {cols.map((col) => (\n                <td key={col.key} className={cell[size]}>\n                  {row[col.key]}\n                </td>\n              ))}\n            </tr>\n          ))}\n        </tbody>\n      </table>\n    </div>\n  )\n}\n\n/* Scroll: sinirli yukseklikte kaydirilan govde, alt kenarda yumusama serit. */\nexport function ScrollTable({ className, size = \"md\", columns, rows }: TableProps) {\n  const { cols, data } = resolve(columns, rows, defaultColumns, longRows)\n  return (\n    <div\n      data-slot=\"styled-table\"\n      className={cn(\"relative w-full rounded-lg border border-border\", className)}\n    >\n      <div className=\"max-h-56 w-full overflow-auto rounded-lg\">\n        <table className={tableBase}>\n          <thead>\n            <tr className=\"border-b border-border bg-muted\">\n              {cols.map((col) => (\n                <th key={col.key} scope=\"col\" className={cn(headBase, headCell[size])}>\n                  {col.label}\n                </th>\n              ))}\n            </tr>\n          </thead>\n          <tbody>\n            {data.map((row, i) => (\n              <tr key={i} className=\"border-b border-border/60 last:border-b-0\">\n                {cols.map((col) => (\n                  <td key={col.key} className={cell[size]}>\n                    {row[col.key]}\n                  </td>\n                ))}\n              </tr>\n            ))}\n          </tbody>\n        </table>\n      </div>\n      <div\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-x-0 bottom-0 h-8 rounded-b-lg bg-gradient-to-t from-[color-mix(in_oklab,var(--color-background)_90%,transparent)] to-transparent\"\n      />\n    </div>\n  )\n}\n\n/* Fixed: table-fixed ile esit kolon genisligi, tasan metin kirpilir. */\nexport function FixedTable({ className, size = \"md\", columns, rows }: TableProps) {\n  const { cols, data } = resolve(columns, rows, defaultColumns, fixedRows)\n  return (\n    <div\n      data-slot=\"styled-table\"\n      className={cn(\"w-full overflow-hidden rounded-lg border border-border\", className)}\n    >\n      <table className={cn(tableBase, \"table-fixed\")}>\n        <thead>\n          <tr className=\"border-b border-border bg-muted\">\n            {cols.map((col) => (\n              <th key={col.key} scope=\"col\" className={cn(headBase, headCell[size], \"truncate\")}>\n                {col.label}\n              </th>\n            ))}\n          </tr>\n        </thead>\n        <tbody>\n          {data.map((row, i) => (\n            <tr key={i} className=\"border-b border-border/60 last:border-b-0\">\n              {cols.map((col) => (\n                <td key={col.key} className={cn(cell[size], \"truncate\")}>\n                  {row[col.key]}\n                </td>\n              ))}\n            </tr>\n          ))}\n        </tbody>\n      </table>\n    </div>\n  )\n}\n\n/* Wide: the multi-column data set scrolls horizontally while the first column stays stuck to the left. */\nexport function WideTable({ className, size = \"md\", columns, rows }: TableProps) {\n  const { cols, data } = resolve(columns, rows, wideColumns, wideRows)\n  return (\n    <div\n      data-slot=\"styled-table\"\n      className={cn(\"w-full overflow-x-auto rounded-lg border border-border\", className)}\n    >\n      <table className={cn(tableBase, \"min-w-[52rem]\")}>\n        <thead>\n          <tr className=\"border-b border-border\">\n            {cols.map((col, j) => (\n              <th\n                key={col.key}\n                scope=\"col\"\n                className={cn(\n                  headBase,\n                  headCell[size],\n                  \"bg-muted whitespace-nowrap\",\n                  j === 0 && \"sticky left-0 z-10 border-r border-border\"\n                )}\n              >\n                {col.label}\n              </th>\n            ))}\n          </tr>\n        </thead>\n        <tbody>\n          {data.map((row, i) => (\n            <tr key={i} className=\"border-b border-border/60 last:border-b-0\">\n              {cols.map((col, j) => (\n                <td\n                  key={col.key}\n                  className={cn(\n                    cell[size],\n                    \"whitespace-nowrap\",\n                    j === 0 &&\n                      \"sticky left-0 z-10 border-r border-border bg-background font-medium\"\n                  )}\n                >\n                  {row[col.key]}\n                </td>\n              ))}\n            </tr>\n          ))}\n        </tbody>\n      </table>\n    </div>\n  )\n}\n\n/* Dense: cok yogun satirlar, ince ayraclar, maksimum veri yogunlugu. */\nexport function DenseTable({ className, size = \"md\", columns, rows }: TableProps) {\n  const { cols, data } = resolve(columns, rows, defaultColumns, longRows)\n  return (\n    <div\n      data-slot=\"styled-table\"\n      className={cn(\"w-full overflow-x-auto rounded-lg border border-border\", className)}\n    >\n      <table className={cn(tableBase, \"leading-tight\")}>\n        <thead>\n          <tr className=\"border-b border-border bg-muted\">\n            {cols.map((col) => (\n              <th\n                key={col.key}\n                scope=\"col\"\n                className={cn(headBase, denseCell[size], \"whitespace-nowrap uppercase tracking-wide\")}\n              >\n                {col.label}\n              </th>\n            ))}\n          </tr>\n        </thead>\n        <tbody>\n          {data.map((row, i) => (\n            <tr\n              key={i}\n              className=\"border-b border-border/40 last:border-b-0 hover:bg-[color-mix(in_oklab,var(--color-foreground)_5%,transparent)]\"\n            >\n              {cols.map((col) => (\n                <td key={col.key} className={cn(denseCell[size], \"whitespace-nowrap\")}>\n                  {row[col.key]}\n                </td>\n              ))}\n            </tr>\n          ))}\n        </tbody>\n      </table>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/table-layout.tsx"
    }
  ],
  "categories": [
    "styled",
    "table"
  ],
  "type": "registry:component"
}