{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-table-demo",
  "type": "registry:example",
  "title": "Data Table Demo",
  "registryDependencies": [
    "https://seamui.dev/r/data-table.json",
    "https://seamui.dev/r/avatar.json",
    "https://seamui.dev/r/badge.json",
    "https://seamui.dev/r/checkbox.json",
    "https://seamui.dev/r/input.json",
    "https://seamui.dev/r/select.json",
    "https://seamui.dev/r/dropdown-menu.json"
  ],
  "files": [
    {
      "path": "registry/seam/examples/data-table-demo.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport type { ColumnDef } from \"@tanstack/react-table\"\n\nimport { Avatar, AvatarFallback } from \"@/registry/seam/ui/avatar\"\nimport { Badge } from \"@/registry/seam/ui/badge\"\nimport { Checkbox } from \"@/registry/seam/ui/checkbox\"\nimport { Input } from \"@/registry/seam/ui/input\"\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/registry/seam/ui/select\"\nimport {\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n} from \"@/registry/seam/ui/dropdown-menu\"\nimport {\n  DataTable,\n  DataTableColumnHeader,\n  DataTableEditableCell,\n  DataTableRowActions,\n  DataTableToolbar,\n} from \"@/registry/seam/ui/data-table\"\n\ntype Status = \"active\" | \"pending\" | \"suspended\"\ntype Role = \"Owner\" | \"Admin\" | \"Member\" | \"Viewer\"\n\ntype Member = {\n  id: string\n  name: string\n  email: string\n  status: Status\n  role: Role\n  amount: number\n}\n\nconst STATUS_VARIANT: Record<Status, \"default\" | \"muted\" | \"destructive\"> = {\n  active: \"default\",\n  pending: \"muted\",\n  suspended: \"destructive\",\n}\n\nconst NAMES = [\n  \"Ava Bradley\",\n  \"Noah Chen\",\n  \"Mia Torres\",\n  \"Liam Novak\",\n  \"Zoe Patel\",\n  \"Ethan Cole\",\n  \"Lily Sato\",\n  \"Owen Reyes\",\n  \"Emma Diaz\",\n  \"Kai Nguyen\",\n  \"Ruby Hale\",\n  \"Leo Fisher\",\n  \"Isla Moon\",\n  \"Finn Park\",\n  \"Nora Wells\",\n]\nconst STATUSES: Status[] = [\"active\", \"pending\", \"suspended\"]\nconst ROLES: Role[] = [\"Owner\", \"Admin\", \"Member\", \"Viewer\"]\n\n// deterministic ~42-row seed so pagination is real.\nconst SEED: Member[] = Array.from({ length: 42 }, (_, i) => {\n  const name = NAMES[i % NAMES.length]\n  const handle = name.toLowerCase().replace(/\\s+/g, \".\")\n  return {\n    id: `usr_${(1042 + i).toString(36)}`,\n    name:\n      i < NAMES.length ? name : `${name} ${Math.floor(i / NAMES.length) + 1}`,\n    email: `${handle}@example.com`,\n    status: STATUSES[i % STATUSES.length],\n    role: ROLES[i % ROLES.length],\n    amount: 40 + ((i * 37) % 960),\n  }\n})\n\nfunction initials(name: string) {\n  return name\n    .split(\" \")\n    .map((part) => part[0])\n    .slice(0, 2)\n    .join(\"\")\n}\n\nexport default function DataTableDemo() {\n  const [data, setData] = React.useState<Member[]>(SEED)\n\n  const updateCell = React.useCallback(\n    (rowIndex: number, columnId: string, value: unknown) => {\n      setData((prev) =>\n        prev.map((row, i) =>\n          i === rowIndex\n            ? {\n                ...row,\n                [columnId]:\n                  columnId === \"amount\" ? Number(value) : (value as string),\n              }\n            : row\n        )\n      )\n    },\n    []\n  )\n\n  const deleteRow = React.useCallback((id: string) => {\n    setData((prev) => prev.filter((row) => row.id !== id))\n  }, [])\n\n  const columns = React.useMemo<ColumnDef<Member>[]>(\n    () => [\n      {\n        id: \"select\",\n        enableSorting: false,\n        enableHiding: false,\n        header: ({ table }) => (\n          <Checkbox\n            checked={table.getIsAllPageRowsSelected()}\n            indeterminate={\n              table.getIsSomePageRowsSelected() &&\n              !table.getIsAllPageRowsSelected()\n            }\n            onCheckedChange={(value) =>\n              table.toggleAllPageRowsSelected(Boolean(value))\n            }\n            aria-label=\"Select all rows on this page\"\n          />\n        ),\n        cell: ({ row }) => (\n          <Checkbox\n            checked={row.getIsSelected()}\n            onCheckedChange={(value) => row.toggleSelected(Boolean(value))}\n            aria-label={`Select ${row.original.name}`}\n          />\n        ),\n      },\n      {\n        accessorKey: \"name\",\n        header: ({ column }) => (\n          <DataTableColumnHeader column={column} title=\"Member\" />\n        ),\n        cell: ({ row }) => (\n          <div className=\"flex items-center gap-3\">\n            <Avatar className=\"size-8\">\n              <AvatarFallback className=\"text-xs\">\n                {initials(row.original.name)}\n              </AvatarFallback>\n            </Avatar>\n            <div className=\"flex flex-col\">\n              <span className=\"font-medium\">{row.original.name}</span>\n              <span className=\"text-muted-foreground text-xs\">\n                {row.original.email}\n              </span>\n            </div>\n          </div>\n        ),\n      },\n      {\n        accessorKey: \"status\",\n        header: \"Status\",\n        filterFn: (row, id, value) => row.getValue(id) === value,\n        cell: ({ row }) => {\n          const status = row.original.status\n          return (\n            <Badge variant={STATUS_VARIANT[status]} className=\"capitalize\">\n              {status}\n            </Badge>\n          )\n        },\n      },\n      {\n        accessorKey: \"role\",\n        header: \"Role\",\n        cell: ({ row, table }) => (\n          <Select\n            value={row.original.role}\n            onValueChange={(value: unknown) =>\n              table.options.meta?.updateData?.(row.index, \"role\", value)\n            }\n          >\n            <SelectTrigger\n              variant=\"ghost\"\n              className=\"-ml-2 h-8\"\n              aria-label={`Role for ${row.original.name}`}\n            >\n              <SelectValue />\n            </SelectTrigger>\n            <SelectContent>\n              {ROLES.map((role) => (\n                <SelectItem key={role} value={role}>\n                  {role}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n        ),\n      },\n      {\n        accessorKey: \"amount\",\n        header: ({ column }) => (\n          <DataTableColumnHeader\n            column={column}\n            title=\"Amount ($)\"\n            align=\"right\"\n          />\n        ),\n        cell: ({ row, table }) => (\n          <DataTableEditableCell\n            align=\"right\"\n            className=\"tabular-nums\"\n            value={row.original.amount}\n            label={`Amount for ${row.original.name}`}\n            validate={(value) => /^\\d+(\\.\\d{1,2})?$/.test(value)}\n            onCommit={(value) =>\n              table.options.meta?.updateData?.(row.index, \"amount\", value)\n            }\n          />\n        ),\n      },\n      {\n        id: \"actions\",\n        enableHiding: false,\n        cell: ({ row }) => (\n          <div className=\"flex justify-end\">\n            <DataTableRowActions label={`Actions for ${row.original.name}`}>\n              <DropdownMenuLabel>Actions</DropdownMenuLabel>\n              <DropdownMenuItem\n                onClick={() => navigator.clipboard?.writeText(row.original.id)}\n              >\n                Copy member ID\n              </DropdownMenuItem>\n              <DropdownMenuItem>View profile</DropdownMenuItem>\n              <DropdownMenuSeparator />\n              <DropdownMenuItem\n                className=\"text-destructive\"\n                onClick={() => deleteRow(row.original.id)}\n              >\n                Delete\n              </DropdownMenuItem>\n            </DataTableRowActions>\n          </div>\n        ),\n      },\n    ],\n    [deleteRow]\n  )\n\n  return (\n    <div className=\"w-full\">\n      <DataTable\n        columns={columns}\n        data={data}\n        getRowId={(row) => row.id}\n        onDataChange={updateCell}\n        label=\"Team members\"\n        toolbar={(table) => (\n          <DataTableToolbar>\n            <Input\n              placeholder=\"Filter members…\"\n              aria-label=\"Filter members by name\"\n              value={\n                (table.getColumn(\"name\")?.getFilterValue() as string) ?? \"\"\n              }\n              onChange={(event) =>\n                table.getColumn(\"name\")?.setFilterValue(event.target.value)\n              }\n              className=\"h-9 w-full sm:w-56\"\n            />\n            <Select\n              value={\n                (table.getColumn(\"status\")?.getFilterValue() as string) ?? \"all\"\n              }\n              onValueChange={(value: unknown) =>\n                table\n                  .getColumn(\"status\")\n                  ?.setFilterValue(value === \"all\" ? undefined : value)\n              }\n            >\n              <SelectTrigger className=\"h-9 w-40\" aria-label=\"Filter by status\">\n                <SelectValue placeholder=\"All statuses\" />\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value=\"all\">All statuses</SelectItem>\n                <SelectItem value=\"active\">Active</SelectItem>\n                <SelectItem value=\"pending\">Pending</SelectItem>\n                <SelectItem value=\"suspended\">Suspended</SelectItem>\n              </SelectContent>\n            </Select>\n          </DataTableToolbar>\n        )}\n      />\n    </div>\n  )\n}\n",
      "type": "registry:example"
    }
  ]
}