iter: b04 新增独立 pagination 分页器并与 dataTable 页码联动
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { h, renderList } from '@ui-arch/frame';
|
||||
import type { PaginationProps } from './types.js';
|
||||
|
||||
/*** 页码序列:≤7 页全展开;否则保留首尾与当前页 ±1 窗口,缺口折叠为省略号(null 占位) ***/
|
||||
function pageSequence(page: number, totalPages: number): (number | null)[] {
|
||||
if (totalPages <= 7) return Array.from({ length: totalPages }, (_, i) => i + 1);
|
||||
const marks = [1, 2, page - 1, page, page + 1, totalPages - 1, totalPages].filter((p) => p >= 1 && p <= totalPages);
|
||||
const seq: (number | null)[] = [];
|
||||
let prev = 0;
|
||||
for (const p of [...new Set(marks)].sort((a, b) => a - b)) {
|
||||
if (p - prev > 1) seq.push(null); // 缺口 → 省略号
|
||||
seq.push(p);
|
||||
prev = p;
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
/*** 独立分页器:受控组件,page 为双向绑定信号;页码过多折叠省略号,首末页禁用翻页,原生 button 保证键盘可达 ***/
|
||||
export function pagination(props: PaginationProps): HTMLElement {
|
||||
const totalPages = Math.max(1, Math.ceil(props.total / props.pageSize)); // 总页数
|
||||
const go = (p: number) => {
|
||||
const next = Math.min(totalPages, Math.max(1, p)); // 钳制到有效页码范围
|
||||
props.page(next);
|
||||
props.onChange?.(next);
|
||||
};
|
||||
|
||||
const nav = h('nav', { class: 'ua-pagination', 'aria-label': '分页' });
|
||||
renderList(nav, () => {
|
||||
const page = Math.min(totalPages, Math.max(1, props.page()));
|
||||
const items: HTMLElement[] = [h('button', { class: 'ua-page-btn', disabled: page <= 1, 'aria-label': '上一页', onClick: () => go(page - 1) }, '‹')];
|
||||
for (const it of pageSequence(page, totalPages)) {
|
||||
items.push(
|
||||
it == null
|
||||
? h('span', { class: 'ua-page-gap', 'aria-hidden': 'true' }, '…')
|
||||
: h('button', { class: `ua-page-btn${it === page ? ' ua-active' : ''}`, disabled: it === page, 'aria-current': it === page ? 'page' : null, 'aria-label': `第 ${it} 页`, onClick: () => go(it) }, String(it)),
|
||||
);
|
||||
}
|
||||
items.push(h('button', { class: 'ua-page-btn', disabled: page >= totalPages, 'aria-label': '下一页', onClick: () => go(page + 1) }, '›'));
|
||||
return items;
|
||||
});
|
||||
return nav;
|
||||
}
|
||||
Reference in New Issue
Block a user