chat-ui / src /lib /components /Pagination.svelte
Mishig
[Assistants] Add pagination (#772)
25a7ba5 unverified
raw
history blame
2.6 kB
<script lang="ts">
import { page } from "$app/stores";
import PaginationArrow from "./PaginationArrow.svelte";
export let classNames = "";
export let numItemsPerPage: number;
export let numTotalItems: number;
const ELLIPSIS_IDX = -1 as const;
const numTotalPages = Math.ceil(numTotalItems / numItemsPerPage);
$: pageIndex = parseInt($page.url.searchParams.get("p") ?? "0");
$: pageIndexes = getPageIndexes(pageIndex);
function getHref(pageIdx: number) {
const newUrl = new URL($page.url);
newUrl.searchParams.set("p", pageIdx.toString());
return newUrl.toString();
}
function getPageIndexes(pageIdx: number) {
let pageIdxs: number[] = [];
const NUM_EXTRA_BUTTONS = 2; // The number of page links to show on either side of the current page link.
const minIdx = 0;
const maxIdx = numTotalPages - 1;
pageIdxs = [pageIdx];
// forward
for (let i = 1; i < NUM_EXTRA_BUTTONS + 1; i++) {
const newPageIdx = pageIdx + i;
if (newPageIdx > maxIdx) {
continue;
}
pageIdxs.push(newPageIdx);
}
if (maxIdx - pageIdxs[pageIdxs.length - 1] > 1) {
pageIdxs.push(...[ELLIPSIS_IDX, maxIdx]);
} else if (maxIdx - pageIdxs[pageIdxs.length - 1] === 1) {
pageIdxs.push(maxIdx);
}
// backward
for (let i = 1; i < NUM_EXTRA_BUTTONS + 1; i++) {
const newPageIdx = pageIdx - i;
if (newPageIdx < minIdx) {
continue;
}
pageIdxs.unshift(newPageIdx);
}
if (pageIdxs[0] - minIdx > 1) {
pageIdxs.unshift(...[minIdx, ELLIPSIS_IDX]);
} else if (pageIdxs[0] - minIdx === 1) {
pageIdxs.unshift(minIdx);
}
return pageIdxs;
}
</script>
{#if numTotalPages > 1}
<nav>
<ul
class="flex select-none items-center justify-between space-x-2 text-gray-700 sm:justify-center dark:text-gray-300 {classNames}"
>
<li>
<PaginationArrow
href={getHref(pageIndex - 1)}
direction="previous"
isDisabled={pageIndex - 1 < 0}
/>
</li>
{#each pageIndexes as pageIdx}
<li class="hidden sm:block">
<a
class="
rounded-lg px-2.5 py-1
{pageIndex === pageIdx
? 'bg-gray-50 font-semibold ring-1 ring-inset ring-gray-200 dark:bg-gray-800 dark:text-yellow-500 dark:ring-gray-700'
: ''}
"
class:pointer-events-none={pageIdx === ELLIPSIS_IDX || pageIndex === pageIdx}
href={getHref(pageIdx)}
>
{pageIdx === ELLIPSIS_IDX ? "..." : pageIdx + 1}
</a>
</li>
{/each}
<li>
<PaginationArrow
href={getHref(pageIndex + 1)}
direction="next"
isDisabled={pageIndex + 1 >= numTotalPages}
/>
</li>
</ul>
</nav>
{/if}