{
  "aliases": [
    "filter-bar",
    "table-state",
    "list-page"
  ],
  "code": "import { useState } from \"react\";\nimport { DataState } from \"@godxjp/ui/query\";\nimport { Card, CardContent, DataTable, EmptyState, type ColumnDef } from \"@godxjp/ui/data-display\";\nimport { SkeletonTable } from \"@godxjp/ui/feedback\";\nimport { SearchInput, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@godxjp/ui/data-entry\";\nimport { Toolbar, ToolbarGroup, Pagination } from \"@godxjp/ui/navigation\";\nimport { Flex } from \"@godxjp/ui/layout\";\nimport { useQuery, keepPreviousData } from \"@tanstack/react-query\";\n\ntype Row = { id: string; name: string; status: string };\n\nexport function MembersTablePage({ orgId }: { orgId?: string }) {\n  const [q, setQ] = useState(\"\");\n  const [status, setStatus] = useState(\"all\");\n  const [page, setPage] = useState(1);\n  const pageSize = 20;\n\n  // placeholderData: keepPreviousData → on page/filter change the PREVIOUS page stays visible\n  // (a stale refresh) instead of flashing a skeleton. enabled gates on the prerequisite (orgId).\n  const query = useQuery({\n    queryKey: [\"members\", orgId, q, status, page],\n    queryFn: () => fetchMembers({ orgId: orgId!, q, status, page, pageSize }),\n    enabled: Boolean(orgId),\n    placeholderData: keepPreviousData,\n  });\n\n  const columns: ColumnDef<Row>[] = [\n    { key: \"name\", header: \"氏名\", render: (r) => <span className=\"font-medium\">{r.name}</span> },\n    { key: \"status\", header: \"ステータス\" },\n  ];\n\n  return (\n    <Flex direction=\"col\" gap=\"lg\">\n      {/* Toolbar (filter bar) is STANDALONE and always visible so the user can change filters even\n          while a query is idle/loading/empty. Changing a filter resets to page 1. It WRAPS, never\n          scrolls sideways (rule #51); more than 2–4 filters → the \"list-filters\" pattern. Never a\n          hand-built Flex/Card of FormFields (ui-audit hand-rolled-filter-bar). */}\n      <Toolbar hasActiveFilters={q !== \"\" || status !== \"all\"}\n        onClear={() => { setQ(\"\"); setStatus(\"all\"); setPage(1); }}>\n        <SearchInput placeholder=\"氏名で検索\" value={q} onSearch={(v) => { setQ(v); setPage(1); }} />\n        <ToolbarGroup label=\"ステータス\">\n          <Select value={status} onValueChange={(v) => { setStatus(v); setPage(1); }}>\n            <SelectTrigger><SelectValue /></SelectTrigger>\n            <SelectContent>\n              <SelectItem value=\"all\">すべて</SelectItem>\n              <SelectItem value=\"active\">有効</SelectItem>\n              <SelectItem value=\"invited\">招待中</SelectItem>\n            </SelectContent>\n          </Select>\n        </ToolbarGroup>\n      </Toolbar>\n\n      {/* The table surface owns exactly ONE card. Pagination lives INSIDE the success branch, so it\n          is hidden during prerequisite / loading / empty / error and for single-page results. */}\n      <DataState\n        query={query}\n        prerequisite={<EmptyState variant=\"section\" title=\"組織を選択してください\" />}\n        skeleton={<Card><CardContent flush><SkeletonTable rows={8} columns={2} /></CardContent></Card>}\n        empty={<EmptyState variant=\"section\" title=\"該当するメンバーがいません\" description=\"検索条件を変更してください。\" />}\n        isEmpty={(d) => d.items.length === 0}\n      >\n        {(d) => {\n          const totalPages = Math.ceil(d.total / pageSize);\n          return (\n            <>\n              <Card><CardContent flush><DataTable data={d.items} columns={columns} getRowId={(r) => r.id} /></CardContent></Card>\n              {totalPages > 1 && (\n                <Pagination value={page} total={d.total} pageSize={pageSize} showTotal onValueChange={setPage} />\n              )}\n            </>\n          );\n        }}\n      </DataState>\n    </Flex>\n  );\n}\n// Responsive: Pagination's showTotal range + controls stack at narrow widths automatically.\n// A transient retry keeps q/status/page (they live in component state, not the query) — the\n// same page reloads in place; the user never loses their filters.",
  "name": "data-table-page",
  "tagline": "Filter (Toolbar) + table surface + bottom pagination driven by a query state machine — pagination shows ONLY for successful multi-page data; filters/page survive a transient retry.",
  "tags": [
    "table",
    "pagination",
    "filter",
    "async",
    "toolbar",
    "datatable"
  ]
}
