iter: d19 dataTable 选中态受控
This commit is contained in:
@@ -200,6 +200,14 @@
|
|||||||
"acceptance": "checkSkinCss():skin-dom 类型包里所有 .css 出现 #hex 字面量即报错并指出文件行号;5 处 #fff 改为 var(--ua-color-bg)(信号色底上的反色,暗色自动翻转);负向测试(临时加 .ua-tmp{color:#fff})能拦下,移除后回归全绿;AGENTS.md 门禁说明同步;npm run check 全绿",
|
"acceptance": "checkSkinCss():skin-dom 类型包里所有 .css 出现 #hex 字面量即报错并指出文件行号;5 处 #fff 改为 var(--ua-color-bg)(信号色底上的反色,暗色自动翻转);负向测试(临时加 .ua-tmp{color:#fff})能拦下,移除后回归全绿;AGENTS.md 门禁说明同步;npm run check 全绿",
|
||||||
"status": "done",
|
"status": "done",
|
||||||
"notes": "rgba(...) 未禁:仅用于阴影与遮罩透明度叠加,不承载品牌色,禁掉会逼出更难读的写法(已在函数注释写明边界);实现上先随 python 写文件把正则转义搞坏两次,改用编辑工具直写并做负向验证确认门禁真实生效"
|
"notes": "rgba(...) 未禁:仅用于阴影与遮罩透明度叠加,不承载品牌色,禁掉会逼出更难读的写法(已在函数注释写明边界);实现上先随 python 写文件把正则转义搞坏两次,改用编辑工具直写并做负向验证确认门禁真实生效"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d19",
|
||||||
|
"title": "dataTable 选中态受控(selected 信号)",
|
||||||
|
"motivation": "选中集只在内核里,外部拿不到也无法预设,批量操作/清空选择只能靠内部工具栏;与 page 受控桥接形成对称能力",
|
||||||
|
"acceptance": "DataTableProps 新增 selected?: Signal<RowKey[]>,与内核选择双向同步(内容比较避免来回派发,外部数组拷贝保护内核);demo 首表传 picked 信号,展示已选计数与「清空选择」按钮;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||||||
|
"status": "done",
|
||||||
|
"notes": "复用 page 桥接的同一套思路:两个 effect 各管一向,sameKeys 内容比较收敛;内部写回拷贝 [...internal],防外部改动内核数组;demo 需 import type { RowKey } 才能对齐 Signal 的逆变"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-23T09:00:48.440Z",
|
"generatedAt": "2026-10-23T09:01:45.831Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
@@ -1253,6 +1253,11 @@
|
|||||||
"n": "loading",
|
"n": "loading",
|
||||||
"t": "boolean | Signal<boolean>",
|
"t": "boolean | Signal<boolean>",
|
||||||
"d": "加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy"
|
"d": "加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"n": "selected",
|
||||||
|
"t": "Signal<RowKey[]>",
|
||||||
|
"d": "受控选中行信号:与内核选择双向同步(内容比较,不来回派发),供批量操作读取/改写"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"example": "dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓名', sortable: true }], pageSize: 5 })",
|
"example": "dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓名', sortable: true }], pageSize: 5 })",
|
||||||
@@ -1266,7 +1271,8 @@
|
|||||||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||||||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||||||
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
||||||
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用"
|
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
||||||
|
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -23,3 +23,4 @@
|
|||||||
{"time": "2026-10-23T16:58:51+08:00", "id": "d16", "result": "done", "summary": "dataTable 消费内核列宽 width:colgroup 固定像素 / flex 自适应,选择列 44px;demo 三列演示宽档;manifest/llms 同步,check 全绿"}
|
{"time": "2026-10-23T16:58:51+08:00", "id": "d16", "result": "done", "summary": "dataTable 消费内核列宽 width:colgroup 固定像素 / flex 自适应,选择列 44px;demo 三列演示宽档;manifest/llms 同步,check 全绿"}
|
||||||
{"time": "2026-10-23T16:59:46+08:00", "id": "d17", "result": "done", "summary": "表单错误态打通包裹式控件:focusout/change 取代 blur + aria-invalid + .ua-invalid 后代选择器覆盖 select/radio/slider;demo 加必填 select;check 全绿"}
|
{"time": "2026-10-23T16:59:46+08:00", "id": "d17", "result": "done", "summary": "表单错误态打通包裹式控件:focusout/change 取代 blur + aria-invalid + .ua-invalid 后代选择器覆盖 select/radio/slider;demo 加必填 select;check 全绿"}
|
||||||
{"time": "2026-10-23T17:00:55+08:00", "id": "d18", "result": "done", "summary": "ua verify 新增皮肤硬编码颜色门禁(#hex 禁止,rgba 仅限阴影/遮罩),清掉 ui.css 5 处 #fff 改令牌;负向测试确认能拦;check 全绿"}
|
{"time": "2026-10-23T17:00:55+08:00", "id": "d18", "result": "done", "summary": "ua verify 新增皮肤硬编码颜色门禁(#hex 禁止,rgba 仅限阴影/遮罩),清掉 ui.css 5 处 #fff 改令牌;负向测试确认能拦;check 全绿"}
|
||||||
|
{"time": "2026-10-23T17:01:46+08:00", "id": "d19", "result": "done", "summary": "dataTable 新增 selected 受控信号:与内核选择双向同步(内容比较 + 拷贝保护),demo 展示已选计数与清空;check 全绿"}
|
||||||
|
|||||||
+13
-1
@@ -30,6 +30,7 @@ import {
|
|||||||
toast,
|
toast,
|
||||||
tooltip,
|
tooltip,
|
||||||
} from '@ui-arch/ui';
|
} from '@ui-arch/ui';
|
||||||
|
import type { RowKey } from '@ui-arch/ui';
|
||||||
|
|
||||||
/*** 侧边目录:挂载后从 .sec 反推锚点,IntersectionObserver 高亮视口内区块(清单改动自动跟随) ***/
|
/*** 侧边目录:挂载后从 .sec 反推锚点,IntersectionObserver 高亮视口内区块(清单改动自动跟随) ***/
|
||||||
function buildToc(toc: HTMLElement, content: HTMLElement): void {
|
function buildToc(toc: HTMLElement, content: HTMLElement): void {
|
||||||
@@ -109,6 +110,9 @@ const tags = signal(['设计', '前端', '组件库']);
|
|||||||
// —— 滑块:音量与禁用态演示 ——
|
// —— 滑块:音量与禁用态演示 ——
|
||||||
const volume = signal(40);
|
const volume = signal(40);
|
||||||
|
|
||||||
|
// —— 受控选中:dataTable 内部勾选实时写回,外部可清空 ——
|
||||||
|
const picked = signal<RowKey[]>([]);
|
||||||
|
|
||||||
// —— 表格加载态:切换后数据行变骨架行,筛选与翻页临时禁用 ——
|
// —— 表格加载态:切换后数据行变骨架行,筛选与翻页临时禁用 ——
|
||||||
const tableLoading = signal(false);
|
const tableLoading = signal(false);
|
||||||
|
|
||||||
@@ -392,7 +396,15 @@ const content = h(
|
|||||||
{ key: 'city', header: '城市', align: 'center', width: 'flex' },
|
{ key: 'city', header: '城市', align: 'center', width: 'flex' },
|
||||||
],
|
],
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
}), h('div', { class: 'row' }, switchButton({ label: '加载态', checked: tableLoading }))),
|
selected: picked,
|
||||||
|
}), h(
|
||||||
|
'div',
|
||||||
|
{ class: 'row' },
|
||||||
|
switchButton({ label: '加载态', checked: tableLoading }),
|
||||||
|
badge({ label: '受控选中', variant: 'default' }),
|
||||||
|
h('span', { class: 'out' }, () => `已选 ${picked().length} 行`),
|
||||||
|
button({ label: '清空选择', variant: 'ghost', onClick: () => picked([]) }),
|
||||||
|
)),
|
||||||
card(
|
card(
|
||||||
{ title: '独立分页器联动(pageSize 3,共用页码信号)' },
|
{ title: '独立分页器联动(pageSize 3,共用页码信号)' },
|
||||||
dataTable({
|
dataTable({
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||||
|
|
||||||
> 自动生成于 2026-10-23T09:00:48.440Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
> 自动生成于 2026-10-23T09:01:45.831Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
@@ -695,6 +695,7 @@ const name = signal(''); const f = form({ onSubmit: submit }, [formItem({ label:
|
|||||||
- selectable(默认 false):boolean —— 启用行选择列:全选三态(含半选)、行 checkbox、已选计数;缺省 false
|
- selectable(默认 false):boolean —— 启用行选择列:全选三态(含半选)、行 checkbox、已选计数;缺省 false
|
||||||
- page:Signal<number> —— 受控页码信号:与内核分页双向同步,传同一个信号给独立 pagination 组件即可联动
|
- page:Signal<number> —— 受控页码信号:与内核分页双向同步,传同一个信号给独立 pagination 组件即可联动
|
||||||
- loading:boolean | Signal<boolean> —— 加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy
|
- loading:boolean | Signal<boolean> —— 加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy
|
||||||
|
- selected:Signal<RowKey[]> —— 受控选中行信号:与内核选择双向同步(内容比较,不来回派发),供批量操作读取/改写
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
|
|
||||||
@@ -714,6 +715,7 @@ dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓
|
|||||||
8. 表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供
|
8. 表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供
|
||||||
9. 数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复
|
9. 数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复
|
||||||
10. 需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用
|
10. 需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用
|
||||||
|
11. 需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)
|
||||||
|
|
||||||
现场演示:apps/docs/demo.html#sec-table
|
现场演示:apps/docs/demo.html#sec-table
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,20 @@ export function dataTable<T extends { id: RowKey }>(props: DataTableProps<T>): H
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// —— 受控选中桥接:外部信号 ↔ 内核选择集;比较内容而非引用,避免来回派发 ——
|
||||||
|
if (props.selected) {
|
||||||
|
const selSig = props.selected;
|
||||||
|
const sameKeys = (a: RowKey[], b: RowKey[]): boolean => a.length === b.length && a.every((k, i) => k === b[i]);
|
||||||
|
effect(() => {
|
||||||
|
const external = selSig();
|
||||||
|
if (!sameKeys(external, state().selection)) table.dispatch({ type: 'setSelection', keys: external }); // 外部改写 → 内核
|
||||||
|
});
|
||||||
|
effect(() => {
|
||||||
|
const internal = state().selection;
|
||||||
|
if (!sameKeys(internal, selSig())) selSig([...internal]); // 内部勾选 → 写回外部(拷贝避免外部改到内核数组)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const filterKey = props.filterKey ?? props.columns[0].key;
|
const filterKey = props.filterKey ?? props.columns[0].key;
|
||||||
const colspan = props.columns.length + (selectable ? 1 : 0);
|
const colspan = props.columns.length + (selectable ? 1 : 0);
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export interface DataTableProps<T> {
|
|||||||
selectable?: boolean; // 是否启用行选择列(含全选三态与已选计数);缺省 false
|
selectable?: boolean; // 是否启用行选择列(含全选三态与已选计数);缺省 false
|
||||||
page?: Signal<number>; // 受控页码信号:与内核分页双向同步,可接独立 pagination 组件联动
|
page?: Signal<number>; // 受控页码信号:与内核分页双向同步,可接独立 pagination 组件联动
|
||||||
loading?: boolean | Signal<boolean>; // 加载态:为真时数据行换成骨架行,筛选与翻页禁用
|
loading?: boolean | Signal<boolean>; // 加载态:为真时数据行换成骨架行,筛选与翻页禁用
|
||||||
|
selected?: Signal<RowKey[]>; // 受控选中行信号:与内核选择双向同步,供批量操作读取
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** 选项条目:select / radioGroup / tabs 共用的选项形状 ***/
|
/*** 选项条目:select / radioGroup / tabs 共用的选项形状 ***/
|
||||||
|
|||||||
@@ -1124,6 +1124,11 @@
|
|||||||
"n": "loading",
|
"n": "loading",
|
||||||
"t": "boolean | Signal<boolean>",
|
"t": "boolean | Signal<boolean>",
|
||||||
"d": "加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy"
|
"d": "加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"n": "selected",
|
||||||
|
"t": "Signal<RowKey[]>",
|
||||||
|
"d": "受控选中行信号:与内核选择双向同步(内容比较,不来回派发),供批量操作读取/改写"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"example": "dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓名', sortable: true }], pageSize: 5 })",
|
"example": "dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓名', sortable: true }], pageSize: 5 })",
|
||||||
@@ -1137,7 +1142,8 @@
|
|||||||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||||||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||||||
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
||||||
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用"
|
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
||||||
|
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user