From aede6c7b3d26cca60956992db44e02010f70fa91 Mon Sep 17 00:00:00 2001 From: eti Date: Tue, 04 Aug 2026 12:18:49 +0000 Subject: [PATCH] web/components: improve Pagination Signed-off-by: eti --- web/src/lib/components/ui/Pagination.stories.svelte | 4 ---- web/src/lib/components/ui/Pagination.svelte | 34 ++++++++++++++++++++++++++-------- 2 file(s) changed, 26 insertion(s)(+), 12 deletion(s)(-) diff --git a/web/src/lib/components/ui/Pagination.stories.svelte b/web/src/lib/components/ui/Pagination.stories.svelte --- a/web/src/lib/components/ui/Pagination.stories.svelte +++ b/web/src/lib/components/ui/Pagination.stories.svelte @@ -9,8 +9,6 @@ argTypes: { page: { control: { type: "number" } }, total: { control: { type: "number" } }, - siblings: { control: { type: "number" } }, - boundaries: { control: { type: "number" } }, labels: { control: { type: "boolean" } }, disabled: { control: { type: "boolean" } } }, @@ -33,5 +31,3 @@ - - diff --git a/web/src/lib/components/ui/Pagination.svelte b/web/src/lib/components/ui/Pagination.svelte --- a/web/src/lib/components/ui/Pagination.svelte +++ b/web/src/lib/components/ui/Pagination.svelte @@ -25,6 +25,26 @@ }); export type PaginationVariants = VariantProps; + + export type PaginationItem = number | "gap-start" | "gap-end"; + + const range = (from: number, to: number): number[] => + Array.from({ length: Math.max(to - from + 1, 0) }, (_, i) => from + i); + + // both ends, the current page and its two neighbours, and the two gaps + const SLOTS = 7; + + // the row is always SLOTS long once a gap is needed, so both gaps are permanent + // residents. that is what lets the plate be placed from an index rather than + // measured, and why paging the middle of a long range moves the numbers, not the row + export function paginate(page: number, count: number): PaginationItem[] { + if (count <= SLOTS) return range(1, count); + // near either end a gap would hide fewer pages than the slots it costs, so the + // window opens flush against that end and only the far gap is drawn + if (page < 4) return [...range(1, 5), "gap-end", count]; + if (page > count - 3) return [1, "gap-start", ...range(count - 4, count)]; + return [1, "gap-start", ...range(page - 1, page + 1), "gap-end", count]; + }