0de9b6e66e
- core/table-core: Headless 表格内核(排序/筛选/分页/选择插件 + 冒烟 9 项) - core/frame: signal/computed/effect + hyperscript 微框架(零依赖) - skin/ui: 16 个 DOM 组件(含自绘 select、滑动指示条 tabs、行选择 dataTable、form 表单校验) - design/tokens: --ua-* 设计令牌(light/dark) - tools/cli: ua 命令行(index/list/info/docs/style/mcp)+ MCP 注册表服务 - apps: demo 演示站(esbuild 单文件)+ docs 双轨文档(人类版 + llms-full.txt)
84 lines
2.7 KiB
JavaScript
84 lines
2.7 KiB
JavaScript
import {
|
|
createTable,
|
|
filterPlugin,
|
|
paginationPlugin,
|
|
selectionPlugin,
|
|
sortPlugin,
|
|
} from '../dist/index.js';
|
|
|
|
const users = [
|
|
{ id: 1, name: 'Charlie', age: 35, city: 'Shenzhen' },
|
|
{ id: 2, name: 'Alice', age: 28, city: 'Beijing' },
|
|
{ id: 3, name: 'Bob', age: 31, city: 'Shanghai' },
|
|
{ id: 4, name: 'Dave', age: 22, city: 'Beijing' },
|
|
{ id: 5, name: 'Eve', age: 29, city: 'Shanghai' },
|
|
];
|
|
|
|
const table = createTable({
|
|
data: users,
|
|
columns: [
|
|
{ key: 'name', header: 'Name', sortable: true },
|
|
{ key: 'age', header: 'Age', sortable: true },
|
|
{ key: 'city', header: 'City' },
|
|
],
|
|
rowKey: 'id',
|
|
plugins: [filterPlugin(), sortPlugin(), paginationPlugin(), selectionPlugin()],
|
|
initialState: { pagination: { page: 1, pageSize: 2 } },
|
|
});
|
|
|
|
/*** 断言工具:失败即退出 ***/
|
|
const assert = (cond, msg) => {
|
|
if (!cond) {
|
|
console.error('FAIL:', msg);
|
|
process.exit(1);
|
|
}
|
|
console.log('ok -', msg);
|
|
};
|
|
|
|
table.dispatch({ type: 'toggleSort', key: 'name' }); // 按名称升序
|
|
assert(
|
|
JSON.stringify(table.getVisibleRows().rows.map((r) => r.name)) ===
|
|
JSON.stringify(['Alice', 'Bob']),
|
|
'sort by name asc + page 1 of size 2',
|
|
);
|
|
|
|
table.dispatch({ type: 'setFilter', key: 'city', value: 'shang' }); // 筛选上海
|
|
const filtered = table.getVisibleRows();
|
|
assert(
|
|
JSON.stringify(filtered.rows.map((r) => r.name)) ===
|
|
JSON.stringify(['Bob', 'Eve']) &&
|
|
filtered.total === 2,
|
|
'filter city~sh keeps Shanghai rows, total=2',
|
|
);
|
|
assert(table.getPageInfo().totalPages === 1, 'totalPages computed from filtered total');
|
|
|
|
table.dispatch({ type: 'clearFilters' }); // 清筛选回到全量
|
|
table.dispatch({ type: 'setPage', page: 2 });
|
|
assert(
|
|
JSON.stringify(table.getVisibleRows().rows.map((r) => r.name)) ===
|
|
JSON.stringify(['Charlie', 'Dave']),
|
|
'page 2 after clearing filter',
|
|
);
|
|
assert(table.getPageInfo().page === 2 && table.getPageInfo().totalPages === 3, 'page info total=3 pages');
|
|
|
|
table.dispatch({ type: 'toggleSelect', key: 3 }); // 勾选行 3
|
|
assert(JSON.stringify(table.getState().selection) === JSON.stringify([3]), 'toggleSelect adds rowKey');
|
|
table.selectAllVisible(); // 全选当前页(替换语义)
|
|
assert(
|
|
JSON.stringify(table.getState().selection) === JSON.stringify([1, 4]),
|
|
'selectAllVisible replaces selection with visible rowKeys',
|
|
);
|
|
|
|
table.dispatch({ type: 'setPage', page: 99 }); // 越界页码
|
|
const clamped = table.getVisibleRows();
|
|
assert(
|
|
table.getPageInfo().page === 3 && clamped.rows.length === 1,
|
|
'page clamped to totalPages',
|
|
);
|
|
|
|
const before = table.getVisibleRows(); // memo 基线
|
|
table.dispatch({ type: 'clearSelection' }); // 无关状态变更
|
|
assert(table.getVisibleRows() === before, 'derive stages memoized across unrelated state changes');
|
|
|
|
console.log('SMOKE OK');
|