This component accept a Page<T> type from [astro](https://docs.astro.build/en/guides/routing/#complete-api-reference)
133 lines
2.8 KiB
Text
133 lines
2.8 KiB
Text
---
|
|
import { type Page } from 'astro';
|
|
|
|
interface Props {
|
|
page: Page;
|
|
paginationOffset?: number;
|
|
urlPattern: string;
|
|
}
|
|
|
|
const { page, urlPattern, paginationOffset = 3 } = Astro.props;
|
|
|
|
const pages = [];
|
|
|
|
const lowerEnd = Math.max(page.currentPage - paginationOffset, 1);
|
|
const highEnd = Math.min(page.currentPage + paginationOffset, page.lastPage);
|
|
|
|
const generateUrl = (index: number) => {
|
|
return urlPattern.replace('{}', index.toString());
|
|
};
|
|
|
|
for (let index = lowerEnd; index <= highEnd; index++) {
|
|
pages.push({
|
|
index,
|
|
url: generateUrl(index),
|
|
});
|
|
}
|
|
---
|
|
|
|
<nav role="navigation" aria-label="Pagination" class="w-100 my-4">
|
|
<ul class="list-unstyle hstack justify-content-center">
|
|
{
|
|
page.url.prev !== undefined && (
|
|
<li>
|
|
<a
|
|
href={page.url.prev}
|
|
class="prev-page"
|
|
aria-label="Go to previous page"
|
|
>
|
|
« Prev
|
|
</a>
|
|
</li>
|
|
)
|
|
}{
|
|
lowerEnd !== 1 && (
|
|
<>
|
|
<li>
|
|
<a
|
|
href={generateUrl(1)}
|
|
class="prev-page"
|
|
aria-label={`Go to page 1`}
|
|
>
|
|
1
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<span class="start-ellipsis">…</span>
|
|
</li>
|
|
</>
|
|
)
|
|
}
|
|
{
|
|
pages.map((item) => (
|
|
<li>
|
|
<a
|
|
class:list={[{ current: item.index === page.currentPage }]}
|
|
href={item.url}
|
|
aria-label={`Go to page ${item.index}`}
|
|
>
|
|
{item.index}
|
|
</a>
|
|
</li>
|
|
))
|
|
}
|
|
{
|
|
highEnd !== page.lastPage && (
|
|
<>
|
|
<li>
|
|
<span class="start-ellipsis">…</span>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href={generateUrl(page.lastPage)}
|
|
class="next-page"
|
|
aria-label={`Go to page ${page.lastPage}`}
|
|
>
|
|
{page.lastPage}
|
|
</a>
|
|
</li>
|
|
</>
|
|
)
|
|
}
|
|
{
|
|
page.url.next !== undefined && (
|
|
<li>
|
|
<a
|
|
href={page.url.next}
|
|
class="next-page"
|
|
aria-label="Go to next page"
|
|
>
|
|
Next »
|
|
</a>
|
|
</li>
|
|
)
|
|
}
|
|
</ul>
|
|
</nav>
|
|
|
|
<style lang="scss">
|
|
li {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
a {
|
|
border: 1px solid var(--prj-link-text);
|
|
padding: var(--prj-spacing-1) var(--prj-spacing-2);
|
|
border-radius: var(--prj-border-radius);
|
|
text-decoration: none;
|
|
transition: background-color 400ms, color 400ms;
|
|
|
|
&.current {
|
|
background-color: var(--prj-secondary);
|
|
border: 1px solid var(--prj-secondary);
|
|
color: var(--prj-secondary-text);
|
|
}
|
|
|
|
&:hover {
|
|
background-color: var(--prj-link-text);
|
|
border: 1px solid var(--prj-link-text);
|
|
color: var(--prj-accent-text);
|
|
text-shadow: none;
|
|
}
|
|
}
|
|
</style>
|