iter(g32): tree 补 ↑↓/Home/End 行间导航
This commit is contained in:
@@ -612,6 +612,14 @@
|
|||||||
"acceptance": "tree({ nodes, expanded, selected, defaultExpandAll, onSelect }) 递归渲染 + 箭头展开收起 + 点选 + Enter/→/← 键盘 + 禁用不响应;组件数 40→41 三处计数同步;npm run check 全绿",
|
"acceptance": "tree({ nodes, expanded, selected, defaultExpandAll, onSelect }) 递归渲染 + 箭头展开收起 + 点选 + Enter/→/← 键盘 + 禁用不响应;组件数 40→41 三处计数同步;npm run check 全绿",
|
||||||
"status": "done",
|
"status": "done",
|
||||||
"notes": "自补:组件补充;selected/expanded 信号均可外部受控"
|
"notes": "自补:组件补充;selected/expanded 信号均可外部受控"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "g32",
|
||||||
|
"title": "tree 补 ↑↓/Home/End 行间导航",
|
||||||
|
"motivation": "tree 只支持 Enter/→/←,无法用键盘在节点间移动焦点,键盘用户仍得靠鼠标找行",
|
||||||
|
"acceptance": "↑↓ 在当前可见节点间移动、Home/End 到首末行,只改焦点不改选中,收起分支的子节点不参与遍历;npm run check 全绿",
|
||||||
|
"status": "open",
|
||||||
|
"notes": "自补:既有组件可用性细节"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-26T03:41:59.549Z",
|
"generatedAt": "2026-10-26T03:43:04.201Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
@@ -1901,7 +1901,7 @@
|
|||||||
"节点树用 { key, label, children } 描述,key 唯一即可(选中与展开都按 key 记)",
|
"节点树用 { key, label, children } 描述,key 唯一即可(选中与展开都按 key 记)",
|
||||||
"传 selected 信号即可外部受控;不传则组件内部维护选中态",
|
"传 selected 信号即可外部受控;不传则组件内部维护选中态",
|
||||||
"点箭头只展开/收起,点标签才选中;叶子节点箭头位置留空以对齐",
|
"点箭头只展开/收起,点标签才选中;叶子节点箭头位置留空以对齐",
|
||||||
"键盘 Enter/空格 选中、→ 展开、← 收起;disabled 节点点击与键盘都不响应",
|
"键盘:↑↓ 在可见节点间移动、Home/End 到首末行(只移动焦点),Enter/空格 选中、→ 展开、← 收起;disabled 节点点击与键盘都不响应",
|
||||||
"defaultExpandAll 首屏展开全部分支(外部已给 expanded 初值时以外部为准)"
|
"defaultExpandAll 首屏展开全部分支(外部已给 expanded 初值时以外部为准)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||||
|
|
||||||
> 自动生成于 2026-10-26T03:41:59.549Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
> 自动生成于 2026-10-26T03:43:04.201Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
@@ -1084,7 +1084,7 @@ const sel = signal(''); tree({ nodes: [{ key: 'src', label: 'src', children: [{
|
|||||||
1. 节点树用 { key, label, children } 描述,key 唯一即可(选中与展开都按 key 记)
|
1. 节点树用 { key, label, children } 描述,key 唯一即可(选中与展开都按 key 记)
|
||||||
2. 传 selected 信号即可外部受控;不传则组件内部维护选中态
|
2. 传 selected 信号即可外部受控;不传则组件内部维护选中态
|
||||||
3. 点箭头只展开/收起,点标签才选中;叶子节点箭头位置留空以对齐
|
3. 点箭头只展开/收起,点标签才选中;叶子节点箭头位置留空以对齐
|
||||||
4. 键盘 Enter/空格 选中、→ 展开、← 收起;disabled 节点点击与键盘都不响应
|
4. 键盘:↑↓ 在可见节点间移动、Home/End 到首末行(只移动焦点),Enter/空格 选中、→ 展开、← 收起;disabled 节点点击与键盘都不响应
|
||||||
5. defaultExpandAll 首屏展开全部分支(外部已给 expanded 初值时以外部为准)
|
5. defaultExpandAll 首屏展开全部分支(外部已给 expanded 初值时以外部为准)
|
||||||
|
|
||||||
现场演示:apps/docs/demo.html#sec-tree
|
现场演示:apps/docs/demo.html#sec-tree
|
||||||
|
|||||||
@@ -72,9 +72,22 @@ export function tree(props: TreeProps): HTMLElement {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*** 当前可见的节点行(收起分支的子节点不参与 ↑↓ 遍历) ***/
|
||||||
|
const visibleRows = (): HTMLElement[] =>
|
||||||
|
Array.from(root.querySelectorAll<HTMLElement>('.ua-tree-row')).filter((el) => !el.closest('.ua-tree-children[hidden]'));
|
||||||
|
|
||||||
root.addEventListener('keydown', (e: KeyboardEvent) => {
|
root.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||||
const row = (e.target as HTMLElement).closest('.ua-tree-row') as HTMLElement | null;
|
const row = (e.target as HTMLElement).closest('.ua-tree-row') as HTMLElement | null;
|
||||||
if (!row) return; // 卫语句:焦点不在节点行
|
if (!row) return; // 卫语句:焦点不在节点行
|
||||||
|
if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {
|
||||||
|
const list = visibleRows();
|
||||||
|
const at = list.indexOf(row);
|
||||||
|
if (at < 0) return; // 卫语句:行已不在可见集
|
||||||
|
e.preventDefault();
|
||||||
|
const next = e.key === 'Home' ? list[0] : e.key === 'End' ? list[list.length - 1] : list[at + (e.key === 'ArrowDown' ? 1 : -1)];
|
||||||
|
next?.focus(); // 行间移动只改焦点,不改变选中
|
||||||
|
return;
|
||||||
|
}
|
||||||
const key = [...rows.entries()].find(([, el]) => el === row)?.[0];
|
const key = [...rows.entries()].find(([, el]) => el === row)?.[0];
|
||||||
if (!key) return; // 卫语句:找不到对应节点
|
if (!key) return; // 卫语句:找不到对应节点
|
||||||
const node = findNode(props.nodes, key);
|
const node = findNode(props.nodes, key);
|
||||||
|
|||||||
@@ -1772,7 +1772,7 @@
|
|||||||
"节点树用 { key, label, children } 描述,key 唯一即可(选中与展开都按 key 记)",
|
"节点树用 { key, label, children } 描述,key 唯一即可(选中与展开都按 key 记)",
|
||||||
"传 selected 信号即可外部受控;不传则组件内部维护选中态",
|
"传 selected 信号即可外部受控;不传则组件内部维护选中态",
|
||||||
"点箭头只展开/收起,点标签才选中;叶子节点箭头位置留空以对齐",
|
"点箭头只展开/收起,点标签才选中;叶子节点箭头位置留空以对齐",
|
||||||
"键盘 Enter/空格 选中、→ 展开、← 收起;disabled 节点点击与键盘都不响应",
|
"键盘:↑↓ 在可见节点间移动、Home/End 到首末行(只移动焦点),Enter/空格 选中、→ 展开、← 收起;disabled 节点点击与键盘都不响应",
|
||||||
"defaultExpandAll 首屏展开全部分支(外部已给 expanded 初值时以外部为准)"
|
"defaultExpandAll 首屏展开全部分支(外部已给 expanded 初值时以外部为准)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user