import {
ChangeDetectionStrategy,
Component,
computed,
input,
model,
numberAttribute,
ViewEncapsulation,
} from "@angular/core";
import { SdAnchor } from "../button/sd-anchor";
import { NgIcon } from "@ng-icons/core";
import {
tablerChevronLeft,
tablerChevronRight,
tablerChevronsLeft,
tablerChevronsRight,
} from "@ng-icons/tabler-icons";
@Component({
selector: "sd-pagination",
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
standalone: true,
imports: [SdAnchor, NgIcon],
template: `
@for (page of displayPages(); track page) {
{{ page }}
}
`,
styles: [
/* language=SCSS */ `
sd-pagination {
> sd-anchor {
display: inline-block;
padding: var(--gap-xs);
}
}
`,
],
host: {
class: "flex-row gap-xs",
},
})
export class SdPagination {
icons = { tablerChevronsLeft, tablerChevronLeft, tablerChevronRight, tablerChevronsRight };
currentPage = model(0);
totalPageCount = input(0, { transform: numberAttribute });
visiblePageCount = input(10, { transform: numberAttribute });
private readonly _groupIndex = computed(() => {
return Math.floor(this.currentPage() / Math.max(this.visiblePageCount(), 1));
});
hasPrev = computed(() => {
if (this.totalPageCount() === 0) {
return false;
}
return this._groupIndex() > 0;
});
hasNext = computed(() => {
const totalPageCount = this.totalPageCount();
if (totalPageCount === 0) {
return false;
}
const lastGroupIndex = Math.floor((totalPageCount - 1) / Math.max(this.visiblePageCount(), 1));
return this._groupIndex() < lastGroupIndex;
});
displayPages = computed(() => {
const totalPageCount = this.totalPageCount();
if (totalPageCount === 0) {
return [] as number[];
}
const visiblePageCount = this.visiblePageCount();
const startPage = this._groupIndex() * visiblePageCount + 1;
const endPage = Math.min(startPage + visiblePageCount - 1, totalPageCount);
const pages: number[] = [];
for (let i = startPage; i <= endPage; i++) {
pages.push(i);
}
return pages;
});
goToPage(page: number): void {
this.currentPage.set(page);
}
goToNextGroup(): void {
this.currentPage.set((this._groupIndex() + 1) * Math.max(this.visiblePageCount(), 1));
}
goToPrevGroup(): void {
if (!this.hasPrev()) return;
this.currentPage.set((this._groupIndex() - 1) * Math.max(this.visiblePageCount(), 1));
}
goToFirst(): void {
this.currentPage.set(0);
}
goToLast(): void {
if (this.totalPageCount() === 0) return;
this.currentPage.set(this.totalPageCount() - 1);
}
}