iter(g24): 新增 list 列表组件(含空状态回落与可点击条目)
This commit is contained in:
@@ -31,6 +31,7 @@ export { stepper } from './stepper.js';
|
||||
export { rate } from './rate.js';
|
||||
export { empty } from './empty.js';
|
||||
export { divider } from './divider.js';
|
||||
export { list } from './list.js';
|
||||
export { descriptions } from './descriptions.js';
|
||||
export { statistic } from './statistic.js';
|
||||
export { timeline } from './timeline.js';
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { h } from '@ui-arch/frame';
|
||||
import type { ListProps } from './types.js';
|
||||
import { empty } from './empty.js';
|
||||
|
||||
/*** 列表:header/footer 外壳 + 逐条 items(avatar / title / description / extra),传 onItemClick 时条目可点击,无数据回落空状态 ***/
|
||||
export function list(props: ListProps): HTMLElement {
|
||||
// —— 状态集中声明 ——
|
||||
const clickable = typeof props.onItemClick === 'function'; // 仅提供回调时才加可点击样式
|
||||
const rootClass = props.bordered ? 'ua-list ua-list-bordered' : 'ua-list'; // 外边框由 bordered 决定
|
||||
const root = h('div', { class: rootClass }) as HTMLElement; // 列表根容器
|
||||
if (props.header) root.append(h('div', { class: 'ua-list-header' }, props.header));
|
||||
if (!props.items.length) {
|
||||
root.append(empty({ title: props.emptyText ?? '暂无数据' })); // 空列表复用空状态组件
|
||||
return root;
|
||||
}
|
||||
const body = h('div', { class: 'ua-list-body', role: 'list' }) as HTMLElement; // 条目容器,供读屏识别列表语义
|
||||
props.items.forEach((item, index) => {
|
||||
const row = h(
|
||||
'div',
|
||||
{ class: clickable ? 'ua-list-item ua-list-clickable' : 'ua-list-item', role: 'listitem' },
|
||||
item.avatar ? h('div', { class: 'ua-list-avatar' }, item.avatar) : null, // 左侧头像/图标,缺省不留位
|
||||
h(
|
||||
'div',
|
||||
{ class: 'ua-list-main' },
|
||||
h('div', { class: 'ua-list-title' }, item.title),
|
||||
item.description ? h('div', { class: 'ua-list-desc' }, item.description) : null,
|
||||
),
|
||||
item.extra ? h('div', { class: 'ua-list-extra' }, item.extra) : null, // 右侧附加(时间、标签)
|
||||
);
|
||||
if (clickable) row.addEventListener('click', () => props.onItemClick?.(item, index)); // 点击回传条目与下标
|
||||
body.append(row);
|
||||
});
|
||||
root.append(body);
|
||||
if (props.footer) root.append(h('div', { class: 'ua-list-footer' }, props.footer));
|
||||
return root;
|
||||
}
|
||||
@@ -402,4 +402,22 @@ export interface StatisticProps {
|
||||
trend?: 'up' | 'down'; // 环比方向:up 红 / down 绿(A 股口径);缺省不渲染
|
||||
}
|
||||
|
||||
/*** 列表条目 ***/
|
||||
export interface ListItem {
|
||||
title: string; // 主标题(必填)
|
||||
description?: string; // 次要说明;缺省不渲染
|
||||
avatar?: unknown; // 左侧头像/图标;缺省不留位
|
||||
extra?: unknown; // 右侧附加内容(时间、标签等);缺省不留位
|
||||
}
|
||||
|
||||
/*** 列表入参 ***/
|
||||
export interface ListProps {
|
||||
items: ListItem[]; // 条目列表,按序渲染
|
||||
header?: string; // 列表头标题;缺省不渲染
|
||||
footer?: string; // 列表尾说明;缺省不渲染
|
||||
bordered?: boolean; // 是否带外边框与分隔线;缺省 false
|
||||
emptyText?: string; // 无数据占位文案;缺省「暂无数据」
|
||||
onItemClick?: (item: ListItem, index: number) => void; // 条目点击回调;提供后条目可点击并带 hover 反馈
|
||||
}
|
||||
|
||||
export type { ColumnDef, RowKey }; // 再导出常用内核类型,方便调用方
|
||||
|
||||
Reference in New Issue
Block a user