/** * Copyright Aquera Inc 2025 * * This source code is licensed under the BSD-3-Clause license found in the * LICENSE file in the root directory of this source tree. */ import { LitElement, html, CSSResultArray, TemplateResult } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import { styles } from './nile-pagination.css'; import NileElement from '../internal/nile-element'; import { calculateTotalPages, getPaginationItems, getHiddenPages, getRangeText, } from './nile-pagination-utils'; @customElement('nile-pagination') export class NilePagination extends NileElement { public static get styles(): CSSResultArray { return [styles]; } @property({attribute: 'totalitems',reflect: true,converter: { fromAttribute: (v: string) => { const n = Number(v); return Number.isFinite(n) && n >= 0 ? Math.floor(n) : 0; }, }, })totalItems: number = 0; @property({attribute: 'currentpage', reflect: true, converter: { fromAttribute: (v: string) => { const n = Number(v); return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 1; }, }, })currentPage: number = 1; @property({attribute: 'pagesize',reflect: true,converter: { fromAttribute: (v: string) => { const n = Number(v); return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 50; }, }, })pageSize: number = 50; @property({ attribute: 'pagesizeoptions', reflect: false, converter: { fromAttribute: (v: string) => { try { const arr = JSON.parse(v); if (Array.isArray(arr) && arr.every(x => typeof x === 'number')) { return arr as number[]; } } catch {} return [10, 25, 50, 100]; }}}) pageSizeOptions: number[] = [10, 25, 50, 100]; @property({ type: String })variant: 'fluid' | 'compact' | 'mini' = 'fluid'; @property({ type: Boolean, reflect: true }) disabled = false; @property({ type: Boolean }) showTitle = true; @state() private _pageSizeOpen = false; @state() private _pageOpen = false; @state() private _miniPageOpen = false; @query('.page-size-dropdown') private _pageSizeDropdown!: HTMLElement; firstUpdated() { if (this._pageSizeDropdown) { this._pageSizeDropdown.addEventListener('nile-show', () => { this._pageSizeOpen = true; }); this._pageSizeDropdown.addEventListener('nile-after-hide', () => { this._pageSizeOpen = false; }); } } private get totalPages(): number { return Math.max(1, calculateTotalPages(this.totalItems, this.pageSize)); } private goToPage(newPage: number) { if (this.disabled) return; const previousPage = this.currentPage; this.currentPage = newPage; this.emit('nile-change', { page: newPage, previousPage, pageSize: this.pageSize }); } private onPageSizeSelect(newSize: number) { if (this.disabled || this.pageSize === newSize) return; const previousPage = this.currentPage; this.pageSize = newSize; this.currentPage = 1; this.emit('nile-change', { page: 1, previousPage, pageSize: newSize }); } private renderCompactRangeText(): TemplateResult { const full = getRangeText(this.totalItems, this.pageSize, this.currentPage); const trimmed = full.replace(/^Showing\s*/, ''); return html`