sync
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
---
|
||||
import { pageHref, pageWindow } from "../lib/pagination";
|
||||
|
||||
interface Props {
|
||||
path: string;
|
||||
params: URLSearchParams;
|
||||
total: number;
|
||||
limit: number;
|
||||
offset: number;
|
||||
anchor?: string;
|
||||
itemLabel?: string;
|
||||
}
|
||||
|
||||
const { path, params, total, limit, offset, anchor = "", itemLabel = "записей" } = Astro.props;
|
||||
const state = pageWindow(total, limit, offset);
|
||||
---
|
||||
{total > limit && <nav class="pagination" aria-label="Пагинация">
|
||||
<span>{state.start}–{state.end} из {total} {itemLabel} · страница {state.page} из {state.pages}</span>
|
||||
<div>
|
||||
{state.previousOffset !== null
|
||||
? <a data-action="secondary" rel="prev" href={pageHref(path, params, state.previousOffset, anchor)}>← Предыдущая</a>
|
||||
: <span class="pagination__disabled" aria-disabled="true">← Предыдущая</span>}
|
||||
{state.nextOffset !== null
|
||||
? <a data-action="secondary" rel="next" href={pageHref(path, params, state.nextOffset, anchor)}>Следующая →</a>
|
||||
: <span class="pagination__disabled" aria-disabled="true">Следующая →</span>}
|
||||
</div>
|
||||
</nav>}
|
||||
@@ -0,0 +1,31 @@
|
||||
export type PageWindow = {
|
||||
start: number;
|
||||
end: number;
|
||||
page: number;
|
||||
pages: number;
|
||||
previousOffset: number | null;
|
||||
nextOffset: number | null;
|
||||
};
|
||||
|
||||
export const pageWindow = (total: number, limit: number, offset: number): PageWindow => {
|
||||
const safeTotal = Math.max(0, Math.trunc(total));
|
||||
const safeLimit = Math.max(1, Math.trunc(limit));
|
||||
const safeOffset = Math.max(0, Math.trunc(offset));
|
||||
const end = Math.min(safeOffset + safeLimit, safeTotal);
|
||||
return {
|
||||
start: safeTotal > 0 && safeOffset < safeTotal ? safeOffset + 1 : 0,
|
||||
end,
|
||||
page: Math.floor(safeOffset / safeLimit) + 1,
|
||||
pages: Math.max(1, Math.ceil(safeTotal / safeLimit)),
|
||||
previousOffset: safeOffset > 0 ? Math.max(0, safeOffset - safeLimit) : null,
|
||||
nextOffset: end < safeTotal ? safeOffset + safeLimit : null,
|
||||
};
|
||||
};
|
||||
|
||||
export const pageHref = (path: string, search: URLSearchParams, offset: number, anchor = "") => {
|
||||
const params = new URLSearchParams(search);
|
||||
if (offset > 0) params.set("offset", String(offset));
|
||||
else params.delete("offset");
|
||||
const query = params.toString();
|
||||
return `${path}${query ? `?${query}` : ""}${anchor}`;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
.pagination{width:min(1360px,calc(100% - 64px));margin:22px auto 48px;display:flex;align-items:center;justify-content:space-between;gap:16px;color:var(--text-secondary);font-size:13px}.pagination>div{display:flex;gap:10px}.pagination a,.pagination__disabled{display:inline-flex;align-items:center;min-height:42px;padding:10px 15px;border:1px solid var(--border-strong);border-radius:10px;background:var(--surface-elevated);color:var(--text-secondary);text-decoration:none}.pagination a:hover{background:var(--surface-raised);color:var(--text-primary)}.pagination__disabled{opacity:.5}@media(max-width:720px){.pagination{width:calc(100% - 28px);align-items:stretch;flex-direction:column}.pagination>div{display:grid;grid-template-columns:1fr 1fr}.pagination a,.pagination__disabled{justify-content:center;text-align:center}}
|
||||
Reference in New Issue
Block a user