Add paginated table content.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Madeorsk 2024-07-29 11:46:03 +02:00
parent 267afa68dd
commit 0bb88b177f
Signed by: Madeorsk
SSH key fingerprint: SHA256:J9G0ofIOLKf7kyS2IfrMqtMaPdfsk1W02+oGueZzDDU
4 changed files with 79 additions and 6 deletions

View file

@ -123,7 +123,7 @@ export function DemoTable()
new Promise((resolve) => {
// Resolving promise in 2s.
window.setTimeout(() => {
resolve(Array.from({ length: 15 }).map(() => {
resolve(Array.from({ length: 43 }).map(() => {
// Compute random quantity and unit price.
const name = randomName();
const quantity = randomQuantity();
@ -166,6 +166,6 @@ export function DemoTable()
), []);
return (
<Smartable.Table data={demoDataPromise} />
<Smartable.Table data={demoDataPromise} paginate={{ pageSize: 6 }} />
);
}

View file

@ -5,6 +5,7 @@ import {RowInstance, RowLoader} from "./Row";
import {useAsyncManager} from "./AsyncManager";
import {ColumnHeading} from "./Columns/ColumnHeading";
import {sortRows} from "./Sort";
import {AutoPaginate} from "@kernelui/core";
/**
* Smartable instance component properties.
@ -20,7 +21,52 @@ export interface InstanceProperties<CK extends ColumnKey> extends SmartablePrope
/**
* Main component for a Smartable table.
*/
export function Instance<CK extends ColumnKey>({columns}: InstanceProperties<CK>)
export function Instance<CK extends ColumnKey>(props: InstanceProperties<CK>)
{
if (props.paginate)
{ // If pagination is enabled.
return <PaginatedInstance {...props} />
}
else
{ // No pagination, simple body render.
return (
<Table {...props}>
<TableBody />
</Table>
);
}
}
/**
* Paginated Smartable instance component.
*/
export function PaginatedInstance<CK extends ColumnKey>(props: InstanceProperties<CK>)
{
// Get data from table.
const {data} = useTable<CK>();
// Get current data state from the async table value.
const {currentDataState} = useAsyncManager<CK>(data);
// Compute page count for the current rows.
const pageCount = Math.ceil((currentDataState?.rows?.length ?? 0) / props.paginate.pageSize);
return (
<AutoPaginate count={pageCount}>
{(page) => (
// Render table with table body of the current page.
<Table {...props}>
<TableBody pagination={{page: page, pageSize: props.paginate.pageSize}} />
</Table>
)}
</AutoPaginate>
);
}
/**
* Base component for a Smartable table.
*/
export function Table<CK extends ColumnKey>({columns, children}: React.PropsWithChildren<InstanceProperties<CK>>)
{
return (
<table className={"smartable"}>
@ -28,7 +74,7 @@ export function Instance<CK extends ColumnKey>({columns}: InstanceProperties<CK>
<ColumnsHeadings columns={columns} />
</thead>
<tbody>
<TableBody />
{children}
</tbody>
</table>
);
@ -65,7 +111,15 @@ export function ColumnsHeadings<CK extends ColumnKey>({columns}: {columns: Colum
);
}
export function TableBody<CK extends ColumnKey>()
/**
* Smartable table body.
*/
export function TableBody<CK extends ColumnKey>({pagination}: {
/**
* Current pagination state.
*/
pagination?: { page: number; pageSize: number; };
})
{
// Get data from table.
const {data, columns, columnsSortState, columnsFilterStates} = useTable<CK>();
@ -85,10 +139,17 @@ export function TableBody<CK extends ColumnKey>()
), [currentDataState.rows, columnsFilterStates]);
// Memorize sorted rows.
const sortedRows = useMemo(() => (
let sortedRows = useMemo(() => (
// Sort rows with the current columns sort state.
sortRows<CK>(filteredRows, columns, columnsSortState)
), [filteredRows, columns, columnsSortState]);
if (pagination)
{ // If pagination is enabled, showing only content of the current page.
const startIndex = (pagination.page - 1) * pagination.pageSize;
sortedRows = sortedRows?.slice(startIndex, startIndex + pagination.pageSize);
}
return (
sortedRows ? (
sortedRows.map((rowData, index) => (

View file

@ -34,6 +34,16 @@ export interface SmartableProperties<CK extends ColumnKey>
* Default column heading element.
*/
columnHeadingElement?: React.ReactElement;
/**
* Table rows pagination.
*/
paginate?: {
/**
* Number of rows per page.
*/
pageSize: number;
};
}
/**

View file

@ -1,5 +1,7 @@
table.smartable
{
margin: 0.5em auto;
@import "_cells";
@import "_filters";
@import "_headings";