summaryrefslogtreecommitdiffstatshomepage
path: root/frontend/src/lib/pagination/Pagination.svelte
blob: fc2935c6f9137fdb8b3a1c8291553d002c9a75e1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<script lang="ts">
	import type { PaginationData } from '$lib/Navigation';
	import Target from './Target.svelte';

	interface Props {
		context?: number;
		pagination: PaginationData;
		total: number;
	}

	let { context = 2, pagination, total }: Props = $props();

	let totalPages = $derived(Math.ceil(total / pagination.items));
	let rightBoundary = $derived(pagination.page - context);
	let leftBoundary = $derived(pagination.page + context);

	let shiftRight = $derived(leftBoundary - totalPages);
	let shiftLeft = $derived(1 - rightBoundary);

	let containedLeft = $derived(leftBoundary <= totalPages);
	let containedRight = $derived(rightBoundary > 0);

	let start = $derived(Math.max(1, containedLeft ? rightBoundary : rightBoundary - shiftRight));
	let end = $derived(
		Math.min(totalPages, containedRight ? leftBoundary : leftBoundary + shiftLeft)
	);

	let leftmost = $derived(pagination.page <= 1);
	let rightmost = $derived(pagination.page >= totalPages);
</script>

{#if totalPages > 1}
	<div class="flex justify-center gap-2">
		<Target disabled={leftmost} target={1}>
			<span class="icon-base icon-[material-symbols--keyboard-double-arrow-left]"></span>
		</Target>
		<Target disabled={leftmost} target={pagination.page - 1}>
			<span class="icon-base icon-[material-symbols--keyboard-arrow-left]"></span>
		</Target>
		{#each Array.from({ length: end + 1 - start }, (_, i) => i + start) as target}
			<Target active={pagination.page === target} {target}>
				<p>{target.toString()}</p>
			</Target>
		{/each}
		<Target disabled={rightmost} target={pagination.page + 1}>
			<span class="icon-base icon-[material-symbols--keyboard-arrow-right]"></span>
		</Target>
		<Target disabled={rightmost} target={totalPages}>
			<span class="icon-base icon-[material-symbols--keyboard-double-arrow-right]"></span>
		</Target>
	</div>
{/if}