iter(g256): 抽出分页条并加每页条数切换
This commit is contained in:
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-26T14:17:04.411Z",
|
"generatedAt": "2026-10-26T14:19:01.143Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
@@ -2087,6 +2087,7 @@
|
|||||||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||||||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||||||
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
||||||
|
"分页条自带每页条数下拉(5 / 10 / 20 条,调用方传的 pageSize 若不在候选里会自动补进去):切换即改页大小并回第 1 页,首末页时上/下一页置灰不再派发无效页码",
|
||||||
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
||||||
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)",
|
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)",
|
||||||
"可排序表头的 aria-sort 跟随排序态同步(ascending / descending / none),读屏能直接播报当前列序,箭头只是视觉补充",
|
"可排序表头的 aria-sort 跟随排序态同步(ascending / descending / none),读屏能直接播报当前列序,箭头只是视觉补充",
|
||||||
|
|||||||
+7
-6
@@ -1,6 +1,6 @@
|
|||||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||||
|
|
||||||
> 自动生成于 2026-10-26T14:17:04.411Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
> 自动生成于 2026-10-26T14:19:01.143Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
@@ -1037,11 +1037,12 @@ dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓
|
|||||||
8. 工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行
|
8. 工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行
|
||||||
9. 表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供
|
9. 表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供
|
||||||
10. 数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复
|
10. 数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复
|
||||||
11. 需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用
|
11. 分页条自带每页条数下拉(5 / 10 / 20 条,调用方传的 pageSize 若不在候选里会自动补进去):切换即改页大小并回第 1 页,首末页时上/下一页置灰不再派发无效页码
|
||||||
12. 需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)
|
12. 需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用
|
||||||
13. 可排序表头的 aria-sort 跟随排序态同步(ascending / descending / none),读屏能直接播报当前列序,箭头只是视觉补充
|
13. 需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)
|
||||||
14. 需要导出时开 exportable:按钮导的是筛选+排序后的全量行,与当前页无关,单元格按 format 输出
|
14. 可排序表头的 aria-sort 跟随排序态同步(ascending / descending / none),读屏能直接播报当前列序,箭头只是视觉补充
|
||||||
15. 整行可点(进详情、选中一行做后续操作)传 onRowClick:行会变成可聚焦项,Enter / 空格与点击等价;不传时行不进 Tab 序列,纯展示表不会被读屏当成按钮
|
15. 需要导出时开 exportable:按钮导的是筛选+排序后的全量行,与当前页无关,单元格按 format 输出
|
||||||
|
16. 整行可点(进详情、选中一行做后续操作)传 onRowClick:行会变成可聚焦项,Enter / 空格与点击等价;不传时行不进 Tab 序列,纯展示表不会被读屏当成按钮
|
||||||
|
|
||||||
现场演示:apps/docs/demo.html#sec-table
|
现场演示:apps/docs/demo.html#sec-table
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import {
|
|||||||
import { iconSearch } from './icons.js'; import { computed, effect, h, renderList, signal } from '@ui-arch/frame';
|
import { iconSearch } from './icons.js'; import { computed, effect, h, renderList, signal } from '@ui-arch/frame';
|
||||||
import { attachResize } from './columnResize.js';
|
import { attachResize } from './columnResize.js';
|
||||||
import { exportButton } from './csv.js';
|
import { exportButton } from './csv.js';
|
||||||
import { button } from './button.js';
|
|
||||||
import { skeleton } from './skeleton.js';
|
import { skeleton } from './skeleton.js';
|
||||||
import { textField } from './textField.js';
|
import { textField } from './textField.js';
|
||||||
import { emptyRow } from './tableEmpty.js';
|
import { emptyRow } from './tableEmpty.js';
|
||||||
|
import { tablePager } from './tablePager.js';
|
||||||
import { attachDataSource, readRows } from './tableDataSource.js';
|
import { attachDataSource, readRows } from './tableDataSource.js';
|
||||||
import type { DataTableProps, TableApi } from './types.js';
|
import type { DataTableProps, TableApi } from './types.js';
|
||||||
|
|
||||||
@@ -188,12 +188,12 @@ export function dataTable<T extends { id: RowKey }>(props: DataTableProps<T>): H
|
|||||||
props.exportable ? exportButton(table, props.columns, props.exportName ?? 'table.csv') : null, // 导出筛选+排序后的全量行
|
props.exportable ? exportButton(table, props.columns, props.exportName ?? 'table.csv') : null, // 导出筛选+排序后的全量行
|
||||||
),
|
),
|
||||||
h('div', { class: 'ua-table-scroll' }, h('table', null, colgroup, h('thead', null, h('tr', null, selectable ? headCheck : null, ...props.columns.map(th))), tbody)),
|
h('div', { class: 'ua-table-scroll' }, h('table', null, colgroup, h('thead', null, h('tr', null, selectable ? headCheck : null, ...props.columns.map(th))), tbody)),
|
||||||
h(
|
tablePager({
|
||||||
'div',
|
info,
|
||||||
{ class: 'ua-pager', role: 'navigation', 'aria-label': '分页' },
|
total: () => visible().total,
|
||||||
button({ label: '上一页', variant: 'ghost', disabled: props.loading, onClick: () => table.dispatch({ type: 'setPage', page: info().page - 1 }) }),
|
loading: busy,
|
||||||
h('span', { class: 'ua-page-info', role: 'status', 'aria-live': 'polite' }, () => `第 ${info().page} / ${info().totalPages} 页 · 共 ${visible().total} 行`), // 翻页/筛选后面向读屏播报
|
onPage: (page) => table.dispatch({ type: 'setPage', page }),
|
||||||
button({ label: '下一页', variant: 'ghost', disabled: props.loading, onClick: () => table.dispatch({ type: 'setPage', page: info().page + 1 }) }),
|
onPageSize: (pageSize) => table.dispatch({ type: 'setPageSize', pageSize }),
|
||||||
),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { effect, h, signal } from '@ui-arch/frame';
|
||||||
|
import { button } from './button.js';
|
||||||
|
import { select } from './select.js';
|
||||||
|
import type { TablePagerProps } from './types.js';
|
||||||
|
|
||||||
|
/*** 表格分页条:上一页 / 页码播报 / 下一页 + 每页条数切换;页码与总页数都是内核派生快照,这里只读不持有 ***/
|
||||||
|
export function tablePager(props: TablePagerProps): HTMLElement {
|
||||||
|
const sizes = props.pageSizes ?? [5, 10, 20]; // 每页条数候选:默认三档,够覆盖表格常见密度
|
||||||
|
const initial = props.info().pageSize; // 调用方在建表时可能传了候选外的页大小,补进候选避免下拉显示空白
|
||||||
|
const list = sizes.includes(initial) ? sizes : [...sizes, initial].sort((a, b) => a - b);
|
||||||
|
const sizeSig = signal(String(initial)); // 下拉受控值:外部(内核)改页大小时由下方 effect 同步
|
||||||
|
const atFirst = () => props.info().page <= 1; // 首/末页边界:按钮置灰,避免派发无效页码
|
||||||
|
const atLast = () => props.info().page >= props.info().totalPages;
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
const cur = String(props.info().pageSize);
|
||||||
|
if (cur !== sizeSig()) sizeSig(cur); // 内核页大小变化(含列表恢复默认)→ 回写下拉
|
||||||
|
});
|
||||||
|
|
||||||
|
const sizeSelect = select({
|
||||||
|
size: 'sm',
|
||||||
|
options: list.map((n) => ({ value: String(n), label: `${n} 条/页` })),
|
||||||
|
value: sizeSig,
|
||||||
|
disabled: () => props.loading(), // 加载中不改页大小:避免与在途结果竞争
|
||||||
|
onChange: (v) => props.onPageSize(Number(v)),
|
||||||
|
});
|
||||||
|
|
||||||
|
return h(
|
||||||
|
'div',
|
||||||
|
{ class: 'ua-pager', role: 'navigation', 'aria-label': '分页' },
|
||||||
|
button({ label: '上一页', variant: 'ghost', disabled: () => props.loading() || atFirst(), onClick: () => props.onPage(Math.max(1, props.info().page - 1)) }),
|
||||||
|
h('span', { class: 'ua-page-info', role: 'status', 'aria-live': 'polite' }, () => `第 ${props.info().page} / ${props.info().totalPages} 页 · 共 ${props.total()} 行`), // 翻页 / 筛选后面向读屏播报
|
||||||
|
button({ label: '下一页', variant: 'ghost', disabled: () => props.loading() || atLast(), onClick: () => props.onPage(Math.min(props.info().totalPages, props.info().page + 1)) }),
|
||||||
|
sizeSelect,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -813,6 +813,16 @@ export interface SpaceProps {
|
|||||||
/*** 表格扩展接口:table-core 实例 + 皮肤层用到的两个取数方法 ***/
|
/*** 表格扩展接口:table-core 实例 + 皮肤层用到的两个取数方法 ***/
|
||||||
export type TableApi<T> = TableInstance<T> & { getPageInfo(): PageInfo; selectAllVisible(): void };
|
export type TableApi<T> = TableInstance<T> & { getPageInfo(): PageInfo; selectAllVisible(): void };
|
||||||
|
|
||||||
|
/*** 分页条入参:取值一律走读取器,保持响应式依赖收集 ***/
|
||||||
|
export interface TablePagerProps {
|
||||||
|
info: () => PageInfo; // 分页快照读取器(page / pageSize / totalPages)
|
||||||
|
total: () => number; // 筛选后总行数,只用于播报文案
|
||||||
|
loading: () => boolean; // 加载态:翻页与改页大小一并禁用
|
||||||
|
pageSizes?: number[]; // 每页条数候选;缺省 [5, 10, 20]
|
||||||
|
onPage: (page: number) => void; // 翻页回调(入参已按边界钳制)
|
||||||
|
onPageSize: (pageSize: number) => void; // 改页大小回调
|
||||||
|
}
|
||||||
|
|
||||||
/*** 锚点导航项 ***/
|
/*** 锚点导航项 ***/
|
||||||
export interface AnchorItem {
|
export interface AnchorItem {
|
||||||
href: string; // 目标区块地址(#id);对应元素须存在于页面上
|
href: string; // 目标区块地址(#id);对应元素须存在于页面上
|
||||||
|
|||||||
@@ -1958,6 +1958,7 @@
|
|||||||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||||||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||||||
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
||||||
|
"分页条自带每页条数下拉(5 / 10 / 20 条,调用方传的 pageSize 若不在候选里会自动补进去):切换即改页大小并回第 1 页,首末页时上/下一页置灰不再派发无效页码",
|
||||||
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
||||||
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)",
|
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)",
|
||||||
"可排序表头的 aria-sort 跟随排序态同步(ascending / descending / none),读屏能直接播报当前列序,箭头只是视觉补充",
|
"可排序表头的 aria-sort 跟随排序态同步(ascending / descending / none),读屏能直接播报当前列序,箭头只是视觉补充",
|
||||||
|
|||||||
Reference in New Issue
Block a user