From 046735a79dcf434e478a75ecfc64d871cf47b506 Mon Sep 17 00:00:00 2001 From: eti Date: Tue, 4 Aug 2026 15:18:49 +0300 Subject: [PATCH] web/components: improve Pagination Signed-off-by: eti --- .../components/ui/Pagination.stories.svelte | 4 --- web/src/lib/components/ui/Pagination.svelte | 34 ++++++++++++++----- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/web/src/lib/components/ui/Pagination.stories.svelte b/web/src/lib/components/ui/Pagination.stories.svelte index c22f0d28..71a64694 100644 --- 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 index fc35a377..ea955b17 100644 --- 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]; + }