|
|
|
@ -220,13 +220,24 @@ function applyGlobalFilter<TData>(
|
|
|
|
|
|
|
|
|
|
|
|
// ── Pagination logic ─────────────────────────────────────────────────────────
|
|
|
|
// ── Pagination logic ─────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function normalizePageSize(size: number): number {
|
|
|
|
|
|
|
|
if (!Number.isFinite(size)) return 1;
|
|
|
|
|
|
|
|
return Math.max(1, Math.floor(size));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function normalizePageIndex(index: number): number {
|
|
|
|
|
|
|
|
if (!Number.isFinite(index)) return 0;
|
|
|
|
|
|
|
|
return Math.max(0, Math.floor(index));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function applyPagination<TData>(
|
|
|
|
function applyPagination<TData>(
|
|
|
|
rows: IndexedRow<TData>[],
|
|
|
|
rows: IndexedRow<TData>[],
|
|
|
|
pagination: PaginationState | undefined
|
|
|
|
pagination: PaginationState | undefined
|
|
|
|
): IndexedRow<TData>[] {
|
|
|
|
): IndexedRow<TData>[] {
|
|
|
|
if (!pagination) return rows;
|
|
|
|
if (!pagination) return rows;
|
|
|
|
const start = pagination.pageIndex * pagination.pageSize;
|
|
|
|
const pageSize = normalizePageSize(pagination.pageSize);
|
|
|
|
return rows.slice(start, start + pagination.pageSize);
|
|
|
|
const start = normalizePageIndex(pagination.pageIndex) * pageSize;
|
|
|
|
|
|
|
|
return rows.slice(start, start + pageSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Table row/cell models ────────────────────────────────────────────────────
|
|
|
|
// ── Table row/cell models ────────────────────────────────────────────────────
|
|
|
|
@ -429,12 +440,12 @@ export function createTable<TData>(config: TableConfig<TData>): TableInstance<TD
|
|
|
|
let globalFilter = $state<string>(config.initialGlobalFilter ?? '');
|
|
|
|
let globalFilter = $state<string>(config.initialGlobalFilter ?? '');
|
|
|
|
let columnVisibility = $state<ColumnVisibilityState>(config.initialColumnVisibility ?? {});
|
|
|
|
let columnVisibility = $state<ColumnVisibilityState>(config.initialColumnVisibility ?? {});
|
|
|
|
let selection = $state<RowSelectionState>(config.initialSelection ?? {});
|
|
|
|
let selection = $state<RowSelectionState>(config.initialSelection ?? {});
|
|
|
|
let pagination = $state<PaginationState>(
|
|
|
|
let pagination = $state<PaginationState>({
|
|
|
|
config.initialPagination ?? {
|
|
|
|
pageIndex: normalizePageIndex(config.initialPagination?.pageIndex ?? 0),
|
|
|
|
pageIndex: 0,
|
|
|
|
pageSize: normalizePageSize(
|
|
|
|
pageSize: config.pagination?.pageSize ?? 10
|
|
|
|
config.initialPagination?.pageSize ?? config.pagination?.pageSize ?? 10
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
let columnPinning = $state<ColumnPinningState>(config.initialColumnPinning ?? {});
|
|
|
|
let columnPinning = $state<ColumnPinningState>(config.initialColumnPinning ?? {});
|
|
|
|
let columnSizing = $state<ColumnSizingState>(config.initialColumnSizing ?? {});
|
|
|
|
let columnSizing = $state<ColumnSizingState>(config.initialColumnSizing ?? {});
|
|
|
|
let rowDetailOpen = $state<RowDetailState>(config.initialRowDetailOpen ?? {});
|
|
|
|
let rowDetailOpen = $state<RowDetailState>(config.initialRowDetailOpen ?? {});
|
|
|
|
@ -460,7 +471,7 @@ export function createTable<TData>(config: TableConfig<TData>): TableInstance<TD
|
|
|
|
|
|
|
|
|
|
|
|
const pageCount = $derived.by(() => {
|
|
|
|
const pageCount = $derived.by(() => {
|
|
|
|
if (!config.pagination?.enabled) return 1;
|
|
|
|
if (!config.pagination?.enabled) return 1;
|
|
|
|
return Math.max(1, Math.ceil(totalRowCount / pagination.pageSize));
|
|
|
|
return Math.max(1, Math.ceil(totalRowCount / normalizePageSize(pagination.pageSize)));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const paginatedRows = $derived.by(() => {
|
|
|
|
const paginatedRows = $derived.by(() => {
|
|
|
|
@ -712,13 +723,13 @@ export function createTable<TData>(config: TableConfig<TData>): TableInstance<TD
|
|
|
|
const canNextPage = $derived.by(() => pagination.pageIndex < pageCount - 1);
|
|
|
|
const canNextPage = $derived.by(() => pagination.pageIndex < pageCount - 1);
|
|
|
|
|
|
|
|
|
|
|
|
function setPageIndex(index: number) {
|
|
|
|
function setPageIndex(index: number) {
|
|
|
|
const clamped = Math.max(0, Math.min(index, pageCount - 1));
|
|
|
|
const clamped = Math.max(0, Math.min(normalizePageIndex(index), pageCount - 1));
|
|
|
|
pagination = { ...pagination, pageIndex: clamped };
|
|
|
|
pagination = { ...pagination, pageIndex: clamped };
|
|
|
|
config.onPaginationChange?.(pagination);
|
|
|
|
config.onPaginationChange?.(pagination);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function setPageSize(size: number) {
|
|
|
|
function setPageSize(size: number) {
|
|
|
|
pagination = { pageIndex: 0, pageSize: size };
|
|
|
|
pagination = { pageIndex: 0, pageSize: normalizePageSize(size) };
|
|
|
|
config.onPaginationChange?.(pagination);
|
|
|
|
config.onPaginationChange?.(pagination);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -739,7 +750,7 @@ export function createTable<TData>(config: TableConfig<TData>): TableInstance<TD
|
|
|
|
|
|
|
|
|
|
|
|
function pinColumn(columnId: string, position: ColumnPinningPosition) {
|
|
|
|
function pinColumn(columnId: string, position: ColumnPinningPosition) {
|
|
|
|
const col = resolvedColumns.find((c) => c.id === columnId);
|
|
|
|
const col = resolvedColumns.find((c) => c.id === columnId);
|
|
|
|
if (!col || col.def.enablePinning === false) return;
|
|
|
|
if (!col || col.def.enablePinning !== true) return;
|
|
|
|
const left = (columnPinning.left ?? []).filter((id) => id !== columnId);
|
|
|
|
const left = (columnPinning.left ?? []).filter((id) => id !== columnId);
|
|
|
|
const right = (columnPinning.right ?? []).filter((id) => id !== columnId);
|
|
|
|
const right = (columnPinning.right ?? []).filter((id) => id !== columnId);
|
|
|
|
if (position === 'left') {
|
|
|
|
if (position === 'left') {
|
|
|
|
|