blob: 408b24c20bc04354a7e63052b17b28d09a799293 [file] [log] [blame]
/**
* @fileoverview A custom element that supports a pagination.
*/
import '../../../elements-sk/modules/icons/first-page-icon-sk';
import '../../../elements-sk/modules/icons/last-page-icon-sk';
import '../../../elements-sk/modules/icons/chevron-left-icon-sk';
import '../../../elements-sk/modules/icons/chevron-right-icon-sk';
import { html } from 'lit-html';
import { define } from '../../../elements-sk/modules/define';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { ResponsePagination } from '../json';
export class PaginationSk extends ElementSk {
private _showPages: number = 5;
private _pagination: ResponsePagination = { size: 10, offset: 0, total: 0 };
private _showPagesOffset = Math.floor(this._showPages / 2);
private _pageButtons: number[] = [];
private _page: number = 0;
private _allPages: number = 0;
constructor() {
super(PaginationSk.template);
this._upgradeProperty('pagination');
this._upgradeProperty('showPages');
this._computePageButtons();
}
private static template = (el: PaginationSk) => html`
<div>
<button
class="action"
data-page="0"
?disabled=${el._onFirstPage()}
@click=${el._update}>
<first-page-icon-sk></first-page-icon-sk>
</button>
<button
class="action"
data-page=${el._page - 1}
?disabled=${el._onFirstPage()}
@click=${el._update}>
<chevron-left-icon-sk></chevron-left-icon-sk>
</button>
${el._pageButtons.map(
(page) => html` <button
data-page=${page}
@click=${el._update}
?disabled=${page === el._page}>
${page + 1}
</button>`
)}
<button
class="action"
data-page=${el._page + 1}
?disabled=${el._onLastPage()}
@click=${el._update}>
<chevron-right-icon-sk></chevron-right-icon-sk>
</button>
<button
class="action"
data-page=${el._allPages - 1}
?disabled=${el._onLastPage()}
@click=${el._update}>
<last-page-icon-sk></last-page-icon-sk>(${el._allPages})
</button>
</div>
`;
connectedCallback(): void {
super.connectedCallback();
this._render();
}
_computePageButtons(): void {
this._pageButtons = [];
this._allPages = Math.ceil(this._pagination.total / this._pagination.size);
this._showPagesOffset = Math.floor(this._showPages / 2);
this._page = Math.floor(this._pagination.offset / this._pagination.size);
const start = Math.max(
Math.min(
this._page - this._showPagesOffset,
this._allPages - this._showPages
),
0
);
const end = Math.min(start + this._showPages - 1, this._allPages - 1);
for (let i = start; i <= end; i++) {
this._pageButtons.push(i);
}
this._render();
}
_update(e: Event): void {
const targetPage = (e.currentTarget! as HTMLElement).dataset.page || '0';
this._pagination.offset = parseFloat(targetPage) * this.pagination.size;
this._computePageButtons();
this.dispatchEvent(
new CustomEvent('page-changed', {
bubbles: true,
detail: { offset: this._pagination.offset },
})
);
}
_onFirstPage(): boolean {
return this._page === 0;
}
_onLastPage(): boolean {
return this._allPages === 0 || this._page === this._allPages - 1;
}
/**
* @prop {Object} pagination - Pagination data {offset, size, total}.
*/
get pagination(): ResponsePagination {
return this._pagination;
}
set pagination(val: ResponsePagination) {
this._pagination = val;
this._computePageButtons();
}
/**
* @prop {Number} showPages - Number of page buttons to display, centered
* around the current page.
*/
get showPages(): number {
return this._showPages;
}
set showPages(val: number) {
this._showPages = val;
this._computePageButtons();
}
}
define('pagination-sk', PaginationSk);