CONTENT-WP-0002-T03 renders manifest columns through a pure row mapper and replaceable cell renderers. Assistant: grok Assistant-Session: 01a1346c-fdff-7741-b1af-b7283661554b
41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { renderCell, type CellRenderer } from "@/components/cell-renderers";
|
|
import { ResultsTable } from "@/components/ResultsTable";
|
|
import { cellSortValue, type BrowserRow, type ColumnDef } from "@/lib/browser-row";
|
|
import { nextSort, sortRows } from "@/lib/sort-rows";
|
|
import type { SortState } from "@/lib/types";
|
|
|
|
export function RecordBrowser({
|
|
rows,
|
|
columns,
|
|
heading = "Records",
|
|
renderers,
|
|
}: {
|
|
rows: BrowserRow[];
|
|
columns: ColumnDef[];
|
|
heading?: string;
|
|
renderers?: Record<string, CellRenderer>;
|
|
}) {
|
|
const [sort, setSort] = useState<SortState | undefined>({ key: columns[0]?.key ?? "name", dir: 1 });
|
|
const ordered = sortRows(rows, sort, cellSortValue);
|
|
const tableColumns = columns.map((column) => ({
|
|
key: column.key,
|
|
label: column.label,
|
|
sortable: true,
|
|
render: (row: BrowserRow) => renderCell(column.key, row, renderers),
|
|
}));
|
|
return (
|
|
<section id="records" aria-labelledby="records-heading" className="mx-auto max-w-7xl px-4 py-14 sm:px-6">
|
|
<h2 id="records-heading" className="mb-6 text-2xl">{heading}</h2>
|
|
<ResultsTable
|
|
columns={tableColumns}
|
|
rows={ordered}
|
|
rowKey={(row) => row.id}
|
|
sort={sort}
|
|
onSort={(key) => setSort((current) => nextSort(current, key))}
|
|
/>
|
|
</section>
|
|
);
|
|
}
|