1193 lines
47 KiB
JSON
1193 lines
47 KiB
JSON
{
|
||
"name": "@ui-arch/ui",
|
||
"type": "skin-dom",
|
||
"description": "DOM 皮肤组件库:button / textField / textarea / slider / checkbox / switch / select / menu / radioGroup / accordion / breadcrumb / card / badge / tag / avatar / alert / toast / tooltip / popover / skeleton / spinner / progress / tabs / pagination / modal / drawer / form / formItem / dataTable,构建在 @ui-arch/frame 与 @ui-arch/table-core 之上,样式只消费 --ua-* 令牌。",
|
||
"tags": [
|
||
"components",
|
||
"dom",
|
||
"skin",
|
||
"table",
|
||
"form",
|
||
"feedback"
|
||
],
|
||
"api": {
|
||
"entry": "src/index.ts",
|
||
"exports": [
|
||
"button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用",
|
||
"textField(props):文本输入,value 信号双向绑定,disabled 支持布尔或信号禁用",
|
||
"textarea(props):多行输入,value 信号双向绑定,disabled 支持布尔或信号禁用",
|
||
"slider(props):滑块,value 信号双向绑定,min/max/step 可配,原生 range 承载键盘交互,右侧可显示当前值",
|
||
"checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用",
|
||
"switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用",
|
||
"select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用",
|
||
"menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭",
|
||
"radioGroup(props):单选组,options + value 信号双向绑定,disabled 整组禁用",
|
||
"accordion(props):折叠面板,标题按钮 + grid 行高过渡,单开(手风琴)或多开,支持禁用面板与 active 信号受控",
|
||
"breadcrumb(props):面包屑,nav + ol 语义结构,末项为当前页(aria-current),有 href 走原生链接、无 href 交给 onNavigate",
|
||
"card(props, ...children):卡片容器",
|
||
"badge(props):徽标,variant = default | success | warning | danger",
|
||
"tag(props):可关闭标签,variant 五档语义色,closable + onClose 支持从数据源移除(纯展示请用 badge)",
|
||
"avatar(props):头像,有 src 渲染图片(alt 用名称)、无 src 用首字占位,size 可调 + 四档语义底色",
|
||
"alert(props):提示条,variant = info | success | warning | danger",
|
||
"toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本(closable 显示关闭按钮,同屏最多 4 条)",
|
||
"tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起",
|
||
"popover(props, trigger):可交互气泡卡片,包裹触发器,默认点击开合 + 点外部 / Esc 收起,content 可放按钮等交互元素",
|
||
"skeleton(props):骨架屏占位,variant = text | rect | circle,text 支持 rows 多行,扫光微动画",
|
||
"pagination(props):独立分页器,page 信号双向绑定,页码过多折叠省略号,首末页禁用翻页,键盘可达",
|
||
"spinner(props):加载指示器,size 控制直径",
|
||
"progress(props):进度条,value 信号驱动 0-100(满格切 success 色);不传 value 退化为不确定态无限往复",
|
||
"tabs(props):标签页,active 信号双向绑定,滑动指示条 + 方向键环形导航,支持禁用页签",
|
||
"modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭,size 三档宽度,footer 提供底部操作区",
|
||
"drawer(props, ...children):抽屉,open 信号驱动侧滑面板,placement 左右可配、width 可调、footer 操作区,遮罩 / × / Esc 关闭",
|
||
"form(props, items):表单容器,布局 + 聚合校验,全部通过才触发 onSubmit",
|
||
"formItem(props, control):表单字段,label + 必填红星 + 规则校验 + 错误区,返回 { el, validate } 句柄",
|
||
"dataTable(props):数据表格,粘性表头 / 行选择(全选三态)/ 排序 / 筛选 / 分页 / 空状态;loading 为真时数据行换骨架行且筛选/翻页禁用,内核为 table-core"
|
||
],
|
||
"keyTypes": [
|
||
"ButtonProps",
|
||
"TextFieldProps",
|
||
"TextareaProps",
|
||
"CheckboxProps",
|
||
"SwitchProps",
|
||
"SelectProps",
|
||
"RadioGroupProps",
|
||
"MenuItem",
|
||
"MenuProps",
|
||
"AccordionItem",
|
||
"AccordionProps",
|
||
"BreadcrumbItem",
|
||
"BreadcrumbProps",
|
||
"OptionItem",
|
||
"CardProps",
|
||
"BadgeProps",
|
||
"AlertProps",
|
||
"ToastProps",
|
||
"TooltipProps",
|
||
"SkeletonProps",
|
||
"PaginationProps",
|
||
"SpinnerProps",
|
||
"ProgressProps",
|
||
"TabsProps",
|
||
"ModalProps",
|
||
"FormRule",
|
||
"FormItemProps",
|
||
"FormItemHandle",
|
||
"FormProps",
|
||
"DataTableProps",
|
||
"PopoverProps",
|
||
"SliderProps",
|
||
"TagProps",
|
||
"DrawerProps",
|
||
"AvatarProps"
|
||
]
|
||
},
|
||
"usage": "const checked = signal(false); checkbox({ label: '同意', checked }); const open = signal(false); modal({ title: '确认', open }, '内容')",
|
||
"conventions": [
|
||
"皮肤不持有业务状态,一律委托 headless 内核或调用方信号",
|
||
"表单类组件统一约定:*Props.value/checked/active 为 Signal 双向绑定,onChange/onInput 为回调",
|
||
"语义色 variant 四档:default|info / success / warning / danger,一律来自令牌,禁止硬编码颜色",
|
||
"无障碍基线:装饰性占位(skeleton)aria-hidden、加载指示(spinner)role=status、关闭按钮必须 aria-label、弹层弹窗 aria-haspopup/expanded、读屏可见的状态一律同步 aria-*"
|
||
],
|
||
"docs": {
|
||
"intro": "28 个 DOM 组件,统一用法:组件是普通函数,传入 props 返回 DOM 节点;需要状态时先创建 signal 再双向绑定。引入 CSS:import '@ui-arch/ui/ui.css'(内部已消费 tokens)。",
|
||
"steps": [
|
||
"安装依赖:pnpm add @ui-arch/ui @ui-arch/frame(workspace 内自动链接)",
|
||
"引入样式:在应用入口 import '@ui-arch/ui/ui.css',暗色主题在根元素设 data-theme='dark'",
|
||
"创建状态:import { signal } from '@ui-arch/frame',如 const name = signal('')",
|
||
"调用组件:const el = textField({ value: name }),把 el 挂到你的容器或配合 h() 组合",
|
||
"读写状态:name() 读、name('张三') 写,界面自动同步,无需手动操作 DOM"
|
||
],
|
||
"components": [
|
||
{
|
||
"id": "button",
|
||
"title": "按钮 Button",
|
||
"demo": "sec-counter",
|
||
"props": [
|
||
{
|
||
"n": "label",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "按钮文案"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'primary' | 'ghost' | 'danger'",
|
||
"d": "视觉强度;缺省 primary",
|
||
"df": "primary"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步"
|
||
},
|
||
{
|
||
"n": "onClick",
|
||
"t": "() => void",
|
||
"k": 1,
|
||
"d": "点击回调"
|
||
}
|
||
],
|
||
"example": "button({ label: '提交', variant: 'primary', onClick: () => console.log('clicked') })",
|
||
"steps": [
|
||
"确定语义强度:主操作用 primary(默认),次要操作用 ghost,危险操作用 danger",
|
||
"绑定 onClick 回调处理点击逻辑",
|
||
"需要禁用态时自行在回调首行卫语句判断,或外层包条件渲染"
|
||
]
|
||
},
|
||
{
|
||
"id": "textField",
|
||
"title": "文本输入 TextField",
|
||
"demo": "sec-bind",
|
||
"props": [
|
||
{
|
||
"n": "value",
|
||
"t": "Signal<string>",
|
||
"d": "双向绑定信号:输入写回信号,信号变化写回输入框"
|
||
},
|
||
{
|
||
"n": "placeholder",
|
||
"t": "string",
|
||
"d": "占位文案"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步"
|
||
},
|
||
{
|
||
"n": "onInput",
|
||
"t": "(value: string) => void",
|
||
"k": 1,
|
||
"d": "输入回调,每次按键触发"
|
||
}
|
||
],
|
||
"example": "const name = signal(''); const el = textField({ value: name, placeholder: '输入名字…', onInput: (v) => console.log(v) })",
|
||
"steps": [
|
||
"先用 signal('') 创建字符串信号",
|
||
"传入 value 完成双向绑定:用户输入自动写回,外部赋值自动回显",
|
||
"在任意响应式位置用 name() 读取最新值,如 () => `你好,${name()}`"
|
||
]
|
||
},
|
||
{
|
||
"id": "textarea",
|
||
"title": "多行输入 Textarea",
|
||
"demo": "sec-form",
|
||
"props": [
|
||
{
|
||
"n": "value",
|
||
"t": "Signal<string>",
|
||
"d": "双向绑定信号"
|
||
},
|
||
{
|
||
"n": "rows",
|
||
"t": "number",
|
||
"d": "初始行数;缺省 3",
|
||
"df": "3"
|
||
},
|
||
{
|
||
"n": "placeholder",
|
||
"t": "string",
|
||
"d": "占位文案"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步"
|
||
},
|
||
{
|
||
"n": "onInput",
|
||
"t": "(value: string) => void",
|
||
"k": 1,
|
||
"d": "输入回调"
|
||
}
|
||
],
|
||
"example": "const bio = signal(''); textarea({ value: bio, rows: 4, placeholder: '一句话介绍…' })",
|
||
"steps": [
|
||
"创建信号并传入 value",
|
||
"用 rows 控制初始高度,用户可纵向拉伸",
|
||
"字数统计等派生逻辑直接在响应式文本里读 bio().length"
|
||
]
|
||
},
|
||
{
|
||
"id": "slider",
|
||
"title": "滑块 Slider",
|
||
"demo": "sec-slider",
|
||
"props": [
|
||
{
|
||
"n": "value",
|
||
"t": "Signal<number>",
|
||
"r": 1,
|
||
"d": "当前值信号,双向绑定:拖动写回,外部赋值同步位置"
|
||
},
|
||
{
|
||
"n": "min",
|
||
"t": "number",
|
||
"d": "最小值;缺省 0",
|
||
"df": "0"
|
||
},
|
||
{
|
||
"n": "max",
|
||
"t": "number",
|
||
"d": "最大值;缺省 100",
|
||
"df": "100"
|
||
},
|
||
{
|
||
"n": "step",
|
||
"t": "number",
|
||
"d": "步长;缺省 1",
|
||
"df": "1"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步"
|
||
},
|
||
{
|
||
"n": "showValue",
|
||
"t": "boolean",
|
||
"d": "是否右侧显示当前值;缺省 true",
|
||
"df": "true"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(value: number) => void",
|
||
"k": 1,
|
||
"d": "拖动回调"
|
||
}
|
||
],
|
||
"example": "const vol = signal(40); slider({ value: vol, min: 0, max: 100, step: 5, onChange: (v) => console.log(v) })",
|
||
"steps": [
|
||
"创建数值信号(初值在 min/max 区间内),传入 value 完成双向绑定",
|
||
"用 min / max / step 限定范围与粒度,如 step: 5 只取 5 的倍数",
|
||
"拖动或按 ←→ 键改变值:原生 range 自带键盘与触屏交互,无需额外处理",
|
||
"只想看拖动条不显示数字时传 showValue: false;需要自定义展示可自行读 signal",
|
||
"禁用场景传 disabled(布尔或信号),置灰且不可拖"
|
||
]
|
||
},
|
||
{
|
||
"id": "checkbox",
|
||
"title": "复选框 Checkbox",
|
||
"demo": "sec-form",
|
||
"props": [
|
||
{
|
||
"n": "checked",
|
||
"t": "Signal<boolean>",
|
||
"d": "勾选状态信号,双向绑定"
|
||
},
|
||
{
|
||
"n": "label",
|
||
"t": "string",
|
||
"d": "右侧文案;缺省只渲染勾选框"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(checked: boolean) => void",
|
||
"k": 1,
|
||
"d": "变更回调"
|
||
}
|
||
],
|
||
"example": "const agreed = signal(false); checkbox({ label: '同意条款', checked: agreed, onChange: (v) => console.log(v) })",
|
||
"steps": [
|
||
"创建布尔信号 agreed = signal(false)",
|
||
"传入 checked 与 label,勾选即写回信号",
|
||
"表单提交前用 agreed() 判断是否勾选"
|
||
]
|
||
},
|
||
{
|
||
"id": "switchButton",
|
||
"title": "开关 Switch",
|
||
"demo": "sec-form",
|
||
"props": [
|
||
{
|
||
"n": "checked",
|
||
"t": "Signal<boolean>",
|
||
"d": "开关状态信号,双向绑定"
|
||
},
|
||
{
|
||
"n": "label",
|
||
"t": "string",
|
||
"d": "左侧文案"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(checked: boolean) => void",
|
||
"k": 1,
|
||
"d": "变更回调"
|
||
}
|
||
],
|
||
"example": "const night = signal(true); switchButton({ label: '夜间模式', checked: night })",
|
||
"steps": [
|
||
"创建布尔信号并传入 checked",
|
||
"轨道与滑块的动画由 CSS 完成,无需干预",
|
||
"状态变化在 onChange 里做副作用(如切换主题)"
|
||
]
|
||
},
|
||
{
|
||
"id": "select",
|
||
"title": "下拉选择 Select(自绘弹层)",
|
||
"demo": "sec-form",
|
||
"props": [
|
||
{
|
||
"n": "options",
|
||
"t": "OptionItem[]",
|
||
"r": 1,
|
||
"d": "选项列表,每项 { value, label }"
|
||
},
|
||
{
|
||
"n": "value",
|
||
"t": "Signal<string>",
|
||
"d": "选中值信号,双向绑定"
|
||
},
|
||
{
|
||
"n": "placeholder",
|
||
"t": "string",
|
||
"d": "未选中时触发器显示的占位文案"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "禁用态:布尔直接置位,传信号则动态同步;禁用时触发器置灰且不展开弹层"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(value: string) => void",
|
||
"k": 1,
|
||
"d": "选中回调"
|
||
}
|
||
],
|
||
"example": "const city = signal(''); select({ options: [{ value: 'bj', label: '北京' }], value: city, placeholder: '选择城市…' })",
|
||
"steps": [
|
||
"准备 options 数组,value 是提交用值、label 是展示文案",
|
||
"创建信号并传入 value;未传时组件内部自持状态",
|
||
"点击触发器展开弹层,点选项写回信号并收起;点外部或按 Esc 也会收起",
|
||
"选中项在弹层中用淡色弱化标记,不抢视觉焦点"
|
||
]
|
||
},
|
||
{
|
||
"id": "menu",
|
||
"title": "下拉菜单 Menu",
|
||
"demo": "sec-menu",
|
||
"props": [
|
||
{
|
||
"n": "label",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "触发器文案"
|
||
},
|
||
{
|
||
"n": "items",
|
||
"t": "MenuItem[]",
|
||
"r": 1,
|
||
"d": "菜单条目:{ value, label, disabled?, danger?, divider? }"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'primary' | 'ghost'",
|
||
"d": "触发器视觉强度;缺省 ghost",
|
||
"df": "ghost"
|
||
},
|
||
{
|
||
"n": "align",
|
||
"t": "'start' | 'end'",
|
||
"d": "弹层对齐方向;缺省 start(与触发器左对齐)",
|
||
"df": "start"
|
||
},
|
||
{
|
||
"n": "onSelect",
|
||
"t": "(value: string) => void",
|
||
"k": 1,
|
||
"d": "选中回调,禁用项不触发"
|
||
}
|
||
],
|
||
"example": "menu({ label: '操作', items: [{ value: 'edit', label: '编辑' }, { value: 'del', label: '删除', danger: true }], onSelect: (v) => console.log(v) })",
|
||
"steps": [
|
||
"准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组",
|
||
"传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'",
|
||
"点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)",
|
||
"键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过",
|
||
"靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true"
|
||
]
|
||
},
|
||
{
|
||
"id": "radioGroup",
|
||
"title": "单选组 RadioGroup",
|
||
"demo": "sec-form",
|
||
"props": [
|
||
{
|
||
"n": "options",
|
||
"t": "OptionItem[]",
|
||
"r": 1,
|
||
"d": "选项列表"
|
||
},
|
||
{
|
||
"n": "value",
|
||
"t": "Signal<string>",
|
||
"d": "选中值信号,双向绑定"
|
||
},
|
||
{
|
||
"n": "disabled",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "整组禁用:全部选项与文案置灰且不可选"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(value: string) => void",
|
||
"k": 1,
|
||
"d": "变更回调"
|
||
}
|
||
],
|
||
"example": "const size = signal('m'); radioGroup({ options: [{ value: 's', label: '小' }, { value: 'm', label: '中' }], value: size })",
|
||
"steps": [
|
||
"创建字符串信号,初值设为默认选项的 value",
|
||
"传入 options 与 value,组内自动互斥",
|
||
"读取 size() 获取当前选中值",
|
||
"需要整组禁用时传 disabled:布尔值静态禁用,也可传信号(如 locked)实现动态锁定"
|
||
]
|
||
},
|
||
{
|
||
"id": "accordion",
|
||
"title": "折叠面板 Accordion",
|
||
"demo": "sec-accordion",
|
||
"props": [
|
||
{
|
||
"n": "items",
|
||
"t": "AccordionItem[]",
|
||
"r": 1,
|
||
"d": "面板列表:{ value, title, content, disabled? }"
|
||
},
|
||
{
|
||
"n": "active",
|
||
"t": "Signal<string>",
|
||
"d": "受控展开面板信号(单开模式);缺省由组件内部持有状态"
|
||
},
|
||
{
|
||
"n": "multiple",
|
||
"t": "boolean",
|
||
"d": "允许多个面板同时展开;缺省 false(手风琴,单开)",
|
||
"df": "false"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(active: string) => void",
|
||
"k": 1,
|
||
"d": "展开变化回调:收起时传空串"
|
||
}
|
||
],
|
||
"example": "accordion({ items: [{ value: 'a', title: '账户设置', content: '内容…' }, { value: 'b', title: '通知', content: h('p', null, '…') }] })",
|
||
"steps": [
|
||
"准备 items:value 作标识、title 作标题、content 可为字符串 / DOM 节点 / 响应式函数",
|
||
"默认手风琴模式:展开一个自动收起其他;需要同时展开多个时传 multiple: true",
|
||
"需要外部控制或读取展开项时传 active 信号(受控单开),否则组件内部自持状态",
|
||
"标题是原生 button:Tab 聚焦、Enter / Space 切换,展开态带 aria-expanded + region 关联",
|
||
"内容区用 grid 行高 0fr → 1fr 过渡,无需测量高度;reduced-motion 用户自动静态切换"
|
||
]
|
||
},
|
||
{
|
||
"id": "breadcrumb",
|
||
"title": "面包屑 Breadcrumb",
|
||
"demo": "sec-breadcrumb",
|
||
"props": [
|
||
{
|
||
"n": "items",
|
||
"t": "BreadcrumbItem[]",
|
||
"r": 1,
|
||
"d": "路径条目:{ label, href? },末项自动视为当前页"
|
||
},
|
||
{
|
||
"n": "separator",
|
||
"t": "string",
|
||
"d": "分隔符;缺省 '/'",
|
||
"df": "/"
|
||
},
|
||
{
|
||
"n": "onNavigate",
|
||
"t": "(item, index) => void",
|
||
"k": 1,
|
||
"d": "无 href 条目的点击回调"
|
||
}
|
||
],
|
||
"example": "breadcrumb({ items: [{ label: '首页', href: '/' }, { label: '设置' }, { label: '账户' }], onNavigate: (it) => console.log(it.label) })",
|
||
"steps": [
|
||
"按层级顺序准备 items,最后一项即当前页,自动渲染为不可点的灰色文字并带 aria-current='page'",
|
||
"需要真实跳转就给条目加 href(渲染 <a>);单页应用想自行接管时不给 href,改用 onNavigate 回调",
|
||
"改分隔符传 separator,如 '›';分隔符对读屏隐藏",
|
||
"语义结构为 nav + ol + li,可直接放进页头或卡片标题栏"
|
||
]
|
||
},
|
||
{
|
||
"id": "card",
|
||
"title": "卡片 Card",
|
||
"demo": "sec-card",
|
||
"props": [
|
||
{
|
||
"n": "title",
|
||
"t": "string",
|
||
"d": "标题;缺省不渲染标题行"
|
||
},
|
||
{
|
||
"n": "...children",
|
||
"t": "unknown[]",
|
||
"d": "任意子节点:字符串 / DOM / 响应式函数"
|
||
}
|
||
],
|
||
"example": "card({ title: '用户表' }, dataTable({ data, columns }))",
|
||
"steps": [
|
||
"card 是容器组件:第一个参数是 props,其余参数是任意子节点",
|
||
"传 title 显示标题行,否则只有内容区",
|
||
"子节点可以混合字符串、DOM 节点与响应式函数"
|
||
]
|
||
},
|
||
{
|
||
"id": "badge",
|
||
"title": "徽标 Badge",
|
||
"demo": "sec-feedback",
|
||
"props": [
|
||
{
|
||
"n": "label",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "徽标文案"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'default' | 'success' | 'warning' | 'danger'",
|
||
"d": "语义色;缺省 default",
|
||
"df": "default"
|
||
}
|
||
],
|
||
"example": "badge({ label: '成功', variant: 'success' })",
|
||
"steps": [
|
||
"选择语义色:default 中性、success 成功、warning 警告、danger 危险",
|
||
"传入 label 即可,纯展示组件无状态",
|
||
"状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button"
|
||
]
|
||
},
|
||
{
|
||
"id": "tag",
|
||
"title": "标签 Tag",
|
||
"demo": "sec-tag",
|
||
"props": [
|
||
{
|
||
"n": "label",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "标签文案"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'default' | 'success' | 'warning' | 'danger' | 'info'",
|
||
"d": "语义色;缺省 default",
|
||
"df": "default"
|
||
},
|
||
{
|
||
"n": "closable",
|
||
"t": "boolean",
|
||
"d": "显示 × 关闭按钮;缺省 false(纯展示)",
|
||
"df": "false"
|
||
},
|
||
{
|
||
"n": "onClose",
|
||
"t": "() => void",
|
||
"k": 1,
|
||
"d": "关闭回调:调用方从数据源移除该项后重新渲染"
|
||
}
|
||
],
|
||
"example": "tag({ label: '前端', variant: 'info', closable: true, onClose: () => remove('前端') })",
|
||
"steps": [
|
||
"纯展示用 badge,需要可移除的标签(筛选项 / 已选条件)用 tag",
|
||
"按语义选 variant:info 中性标记、success 通过、warning 待处理、danger 已失效",
|
||
"closable: true 时必须配 onClose:把数据源里的该项删掉再重渲染(组件无状态,不自行摘除节点)",
|
||
"组合用法:容器里用 renderList 按信号数组渲染 tag 列表,删除即写回信号",
|
||
"标签是内联元素,可直接排进 .row 等容器,自动换行由容器决定"
|
||
]
|
||
},
|
||
{
|
||
"id": "avatar",
|
||
"title": "头像 Avatar",
|
||
"demo": "sec-avatar",
|
||
"props": [
|
||
{
|
||
"n": "name",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "名称:生成占位首字,并作为图片 alt 与悬停标题"
|
||
},
|
||
{
|
||
"n": "src",
|
||
"t": "string",
|
||
"d": "图片地址;缺省用首字占位"
|
||
},
|
||
{
|
||
"n": "size",
|
||
"t": "number",
|
||
"d": "直径像素;缺省 32",
|
||
"df": "32"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'default' | 'success' | 'warning' | 'danger'",
|
||
"d": "占位底色语义档;缺省 default",
|
||
"df": "default"
|
||
}
|
||
],
|
||
"example": "avatar({ name: '张三' }); avatar({ name: 'Alice', size: 40, variant: 'success' })",
|
||
"steps": [
|
||
"只传 name:用名称首字做占位(中文取首字、英文大写),底色走 accent 淡化,暗色自动适配",
|
||
"有图片就传 src:渲染 img 并用 name 作 alt,读屏语义完整;图片缺失时由浏览器 alt 兜底",
|
||
"尺寸用 size(像素)控制,头像不参与布局拉伸(flex:none),可安全排进 .row 与表格单元格",
|
||
"需要区分类别(在线/告警)时用 variant 换底色档,颜色一律来自令牌"
|
||
]
|
||
},
|
||
{
|
||
"id": "alert",
|
||
"title": "提示条 Alert",
|
||
"demo": "sec-feedback",
|
||
"props": [
|
||
{
|
||
"n": "message",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "提示内容"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'info' | 'success' | 'warning' | 'danger'",
|
||
"d": "语义色;缺省 info",
|
||
"df": "info"
|
||
}
|
||
],
|
||
"example": "alert({ message: '操作可能存在风险', variant: 'warning' })",
|
||
"steps": [
|
||
"按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误",
|
||
"传入 message 即可,入场自带下滑动画",
|
||
"需要可关闭或带操作按钮时,外层用 h() 组合 button 自行拼装,alert 只负责语义底色"
|
||
]
|
||
},
|
||
{
|
||
"id": "skeleton",
|
||
"title": "骨架屏 Skeleton",
|
||
"demo": "sec-skeleton",
|
||
"props": [
|
||
{
|
||
"n": "variant",
|
||
"t": "'text' | 'rect' | 'circle'",
|
||
"d": "占位形状;缺省 rect(整块矩形)",
|
||
"df": "rect"
|
||
},
|
||
{
|
||
"n": "rows",
|
||
"t": "number",
|
||
"d": "text 形状的行数;缺省 3,末行自动缩短模拟段落",
|
||
"df": "3"
|
||
}
|
||
],
|
||
"example": "skeleton({ variant: 'text', rows: 3 }); skeleton({ variant: 'circle' }); skeleton({ variant: 'rect' })",
|
||
"steps": [
|
||
"数据加载期间用 skeleton 顶替真实内容,加载完成后整体替换",
|
||
"文本段落用 variant: 'text' + rows 控制行数,头像用 'circle',卡片/图片区域用 'rect'",
|
||
"占位块自带扫光动画,reduced-motion 用户自动静态化为纯灰块",
|
||
"组合布局:skeleton 是普通 DOM,可放进 card / row 等任意容器"
|
||
]
|
||
},
|
||
{
|
||
"id": "toast",
|
||
"title": "消息提示 Toast",
|
||
"demo": "sec-toast",
|
||
"props": [
|
||
{
|
||
"n": "message",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "提示文案"
|
||
},
|
||
{
|
||
"n": "duration",
|
||
"t": "number",
|
||
"d": "自动消失毫秒;缺省 3000",
|
||
"df": "3000"
|
||
},
|
||
{
|
||
"n": "closable",
|
||
"t": "boolean",
|
||
"d": "显示关闭按钮,点 × 立即收起;缺省 false(仅可关闭的 toast 接收指针事件,其余保持穿透)",
|
||
"df": "false"
|
||
},
|
||
{
|
||
"n": "variant",
|
||
"t": "'info' | 'success' | 'warning' | 'danger'",
|
||
"d": "语义色;缺省 info(toast.error 对应 danger)",
|
||
"df": "info"
|
||
}
|
||
],
|
||
"example": "toast.success('保存成功'); toast.error('网络请求失败', 5000)",
|
||
"steps": [
|
||
"直接调用语义工厂:toast.info / success / warning / error(message, duration?),无需先建容器",
|
||
"不传 duration 时默认停留 3 秒后自动淡出并移除节点",
|
||
"多条消息在右上角自动纵向堆叠,互不遮挡",
|
||
"需要完整入参(含 variant)时用 showToast(props);组件挂载容器由内部懒创建,样式随 ui.css 一起引入",
|
||
"同屏最多 4 条,超出自动挤掉最早一条;需要用户主动确认的消息用 showToast({ closable: true }) 给个 ×"
|
||
]
|
||
},
|
||
{
|
||
"id": "tooltip",
|
||
"title": "悬浮提示 Tooltip",
|
||
"demo": "sec-tooltip",
|
||
"props": [
|
||
{
|
||
"n": "content",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "提示文案(纯文本)"
|
||
},
|
||
{
|
||
"n": "placement",
|
||
"t": "'top' | 'bottom'",
|
||
"d": "气泡方位;缺省 top(触发器上方)",
|
||
"df": "top"
|
||
},
|
||
{
|
||
"n": "delay",
|
||
"t": "number",
|
||
"d": "出场延迟毫秒;缺省 150,传 0 立即显示",
|
||
"df": "150"
|
||
},
|
||
{
|
||
"n": "trigger",
|
||
"t": "HTMLElement",
|
||
"r": 1,
|
||
"d": "第二个参数:被包裹的触发器元素(按钮 / 输入框等任意 DOM)"
|
||
}
|
||
],
|
||
"example": "tooltip({ content: '保存后立即生效' }, button({ label: '保存', onClick: save }))",
|
||
"steps": [
|
||
"先创建触发器元素,如 const btn = button({ label: '保存' })",
|
||
"用 tooltip(props, trigger) 包一层:返回带气泡的包裹元素,原触发器仍是独立节点",
|
||
"鼠标移入或键盘聚焦约 150ms 后出场,移出 / 失焦立即收起;按 Esc 可立刻关闭",
|
||
"气泡默认在上方,空间不足或需要避让时传 placement: 'bottom'",
|
||
"气泡 pointer-events: none 不抢指针;判读依赖 aria-describedby + role='tooltip',读屏可读",
|
||
"只做展示:不要在气泡里放可点击元素,需要交互请用 modal 或自绘弹层"
|
||
]
|
||
},
|
||
{
|
||
"id": "popover",
|
||
"title": "气泡卡片 Popover",
|
||
"demo": "sec-popover",
|
||
"props": [
|
||
{
|
||
"n": "content",
|
||
"t": "unknown",
|
||
"r": 1,
|
||
"d": "弹层内容:字符串 / DOM 节点 / 响应式函数,可放按钮等交互元素"
|
||
},
|
||
{
|
||
"n": "title",
|
||
"t": "string",
|
||
"d": "弹层标题;缺省不渲染标题行"
|
||
},
|
||
{
|
||
"n": "placement",
|
||
"t": "'top' | 'bottom'",
|
||
"d": "弹层方位;缺省 bottom(触发器下方)",
|
||
"df": "bottom"
|
||
},
|
||
{
|
||
"n": "trigger",
|
||
"t": "'click' | 'hover'",
|
||
"d": "触发方式;缺省 click",
|
||
"df": "click"
|
||
},
|
||
{
|
||
"n": "delay",
|
||
"t": "number",
|
||
"d": "hover 模式出场延迟毫秒;缺省 150",
|
||
"df": "150"
|
||
},
|
||
{
|
||
"n": "onOpenChange",
|
||
"t": "(open: boolean) => void",
|
||
"k": 1,
|
||
"d": "开合回调"
|
||
},
|
||
{
|
||
"n": "triggerEl(第二个参数)",
|
||
"t": "HTMLElement",
|
||
"r": 1,
|
||
"d": "第二个参数:被包裹的触发器元素"
|
||
}
|
||
],
|
||
"example": "popover({ title: '筛选条件', content: h('div', null, '任意可交互内容') }, button({ label: '筛选' }))",
|
||
"steps": [
|
||
"创建触发器元素,再用 popover(props, trigger) 包一层:返回带弹层的包裹元素",
|
||
"点击触发器开合;点弹层外部或按 Esc 收起(Esc 后焦点回触发器)",
|
||
"content 里可以放 button / checkbox 等交互元素(tooltip 只能纯文本),点击弹层内部不会误关",
|
||
"hover 场景传 trigger: 'hover' + delay 控制多快出场;placement: 'top' 让弹层往上翻",
|
||
"需要感知开合做副作用(如懒加载数据)时用 onOpenChange"
|
||
]
|
||
},
|
||
{
|
||
"id": "spinner",
|
||
"title": "加载指示器 Spinner",
|
||
"demo": "sec-feedback",
|
||
"props": [
|
||
{
|
||
"n": "size",
|
||
"t": "number",
|
||
"d": "直径像素;缺省 18",
|
||
"df": "18"
|
||
}
|
||
],
|
||
"example": "spinner(); spinner({ size: 26 })",
|
||
"steps": [
|
||
"数据加载时插入 spinner(),加载完成移除",
|
||
"用 size 匹配上下文尺寸(按钮内用小号,整页 loading 用大号)",
|
||
"与 skeleton 分工:已知内容结构用 skeleton 占位,只有『在跑』的短等待用 spinner"
|
||
]
|
||
},
|
||
{
|
||
"id": "progress",
|
||
"title": "进度条 Progress",
|
||
"demo": "sec-feedback",
|
||
"props": [
|
||
{
|
||
"n": "value",
|
||
"t": "Signal<number>",
|
||
"d": "当前进度 0-100 信号,变化自动平滑过渡(越界钳制)"
|
||
},
|
||
{
|
||
"n": "showText",
|
||
"t": "boolean",
|
||
"d": "是否显示百分比文字;缺省 true",
|
||
"df": "true"
|
||
}
|
||
],
|
||
"example": "const pct = signal(0); progress({ value: pct }); setInterval(() => pct((pct() + 5) % 105), 400)",
|
||
"steps": [
|
||
"时长未知的加载直接 progress() 不传 value:填充块匀速往复,不显示百分比,读屏读作进行中",
|
||
"创建数值信号 pct = signal(0),范围 0-100(越界自动钳制)",
|
||
"传入 value,填充宽度与百分比文字随信号平滑过渡",
|
||
"进行中填充带流动条纹,到 100% 自动变 success 色并停止条纹",
|
||
"不需要百分比文字时传 showText: false",
|
||
"定量进度用 value 信号:满格自动切 success 色并停止条纹,role=progressbar + aria-valuenow 同步"
|
||
]
|
||
},
|
||
{
|
||
"id": "tabs",
|
||
"title": "标签页 Tabs",
|
||
"demo": "sec-tabs-modal",
|
||
"props": [
|
||
{
|
||
"n": "tabs",
|
||
"t": "OptionItem[]",
|
||
"r": 1,
|
||
"d": "页签列表,每项 { value, label }"
|
||
},
|
||
{
|
||
"n": "active",
|
||
"t": "Signal<string>",
|
||
"d": "当前激活页签 value 信号,双向绑定"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(value: string) => void",
|
||
"k": 1,
|
||
"d": "切换回调"
|
||
}
|
||
],
|
||
"example": "const tab = signal('a'); tabs({ tabs: [{ value: 'a', label: '概览' }, { value: 'b', label: '明细', disabled: true }], active: tab })",
|
||
"steps": [
|
||
"创建信号 tab = signal('a'),初值为默认页签",
|
||
"tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB",
|
||
"点击或方向键(←→ 环形)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点",
|
||
"键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动"
|
||
]
|
||
},
|
||
{
|
||
"id": "pagination",
|
||
"title": "分页器 Pagination",
|
||
"demo": "sec-table",
|
||
"props": [
|
||
{
|
||
"n": "page",
|
||
"t": "Signal<number>",
|
||
"r": 1,
|
||
"d": "当前页码信号,双向绑定:外部赋值自动翻页,点击页码写回信号"
|
||
},
|
||
{
|
||
"n": "pageSize",
|
||
"t": "number",
|
||
"r": 1,
|
||
"d": "每页条数"
|
||
},
|
||
{
|
||
"n": "total",
|
||
"t": "number",
|
||
"r": 1,
|
||
"d": "总条数"
|
||
},
|
||
{
|
||
"n": "onChange",
|
||
"t": "(page: number) => void",
|
||
"k": 1,
|
||
"d": "翻页回调"
|
||
}
|
||
],
|
||
"example": "const page = signal(1); pagination({ page, pageSize: 3, total: 24, onChange: (p) => console.log(p) })",
|
||
"steps": [
|
||
"创建页码信号 page = signal(1),与 pageSize / total 一起传入",
|
||
"页码 ≤7 全部展开;更多时只保留首尾与当前页 ±1,缺口折叠为省略号",
|
||
"首末页自动禁用 ‹ › 翻页按钮,当前页禁点并标记 aria-current",
|
||
"与 dataTable 联动:把同一个 page 信号传给 dataTable 的 page 参数,两处翻页自动同步",
|
||
"键盘可达:全部是原生 button,Tab 聚焦后 Enter / Space 触发"
|
||
]
|
||
},
|
||
{
|
||
"id": "modal",
|
||
"title": "弹窗 Modal",
|
||
"demo": "sec-tabs-modal",
|
||
"props": [
|
||
{
|
||
"n": "open",
|
||
"t": "Signal<boolean>",
|
||
"r": 1,
|
||
"d": "开关信号:true 显示 / false 隐藏"
|
||
},
|
||
{
|
||
"n": "title",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "标题"
|
||
},
|
||
{
|
||
"n": "size",
|
||
"t": "'sm' | 'md' | 'lg'",
|
||
"d": "宽度档位:sm 340px / md 420px / lg 640px;缺省 md",
|
||
"df": "md"
|
||
},
|
||
{
|
||
"n": "footer",
|
||
"t": "unknown",
|
||
"d": "底部操作区内容(常见为按钮组,右对齐);缺省不渲染"
|
||
},
|
||
{
|
||
"n": "onClose",
|
||
"t": "() => void",
|
||
"k": 1,
|
||
"d": "关闭回调(点遮罩、× 或 Esc 触发)"
|
||
},
|
||
{
|
||
"n": "...children",
|
||
"t": "unknown[]",
|
||
"d": "弹窗内容子节点"
|
||
}
|
||
],
|
||
"example": "const open = signal(false); modal({ title: '确认操作', open, onClose: () => open(false) }, h('p', null, '内容'))",
|
||
"steps": [
|
||
"创建布尔信号 open = signal(false),弹窗初始隐藏",
|
||
"把 open 传给 modal,其余参数为弹窗内容子节点",
|
||
"打开:open(true);关闭:open(false),点遮罩或 × 会自动写回 false",
|
||
"入场自带遮罩淡入 + 弹窗上浮动画",
|
||
"底部操作按钮放进 footer(如取消/确定),需要更宽内容用 size: 'lg',窄确认框用 'sm'"
|
||
]
|
||
},
|
||
{
|
||
"id": "drawer",
|
||
"title": "抽屉 Drawer",
|
||
"demo": "sec-drawer",
|
||
"props": [
|
||
{
|
||
"n": "title",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "标题"
|
||
},
|
||
{
|
||
"n": "open",
|
||
"t": "Signal<boolean>",
|
||
"r": 1,
|
||
"d": "开关信号:true 滑出 / false 收起"
|
||
},
|
||
{
|
||
"n": "placement",
|
||
"t": "'left' | 'right'",
|
||
"d": "滑出方向;缺省 right",
|
||
"df": "right"
|
||
},
|
||
{
|
||
"n": "width",
|
||
"t": "number",
|
||
"d": "面板宽度像素(窄屏最多 92vw);缺省 320",
|
||
"df": "320"
|
||
},
|
||
{
|
||
"n": "footer",
|
||
"t": "unknown",
|
||
"d": "底部操作区内容;缺省不渲染"
|
||
},
|
||
{
|
||
"n": "onClose",
|
||
"t": "() => void",
|
||
"k": 1,
|
||
"d": "关闭回调(点遮罩 / × / Esc 触发)"
|
||
},
|
||
{
|
||
"n": "...children",
|
||
"t": "unknown[]",
|
||
"d": "面板内容子节点"
|
||
}
|
||
],
|
||
"example": "const open = signal(false); drawer({ title: '详情', open, width: 360, onClose: () => open(false) }, h('p', null, '内容'))",
|
||
"steps": [
|
||
"创建布尔信号 open = signal(false),传给 drawer;其余参数为面板内容子节点",
|
||
"打开后从侧边滑出:placement: 'right'(默认)或 'left',width 控制宽度(窄屏自动收到 92vw)",
|
||
"点遮罩、× 或按 Esc 关闭并写回 false;打开时焦点落在面板首个可交互元素",
|
||
"底部操作按钮放进 footer;与 modal 的分工:modal 是强打断的确认,drawer 保留主视图上下文做详情/编辑",
|
||
"面板内容与 modal 一样接受任意 DOM 与响应式函数"
|
||
]
|
||
},
|
||
{
|
||
"id": "form",
|
||
"title": "表单 Form / 表单字段 FormItem",
|
||
"demo": "sec-formlab",
|
||
"props": [
|
||
{
|
||
"n": "layout",
|
||
"t": "'vertical' | 'horizontal'",
|
||
"d": "布局方向;缺省 vertical(horizontal 为标签左置)",
|
||
"df": "vertical"
|
||
},
|
||
{
|
||
"n": "submitText",
|
||
"t": "string",
|
||
"d": "提交按钮文案;缺省「提交」"
|
||
},
|
||
{
|
||
"n": "resetText",
|
||
"t": "string",
|
||
"d": "重置按钮文案;缺省不渲染"
|
||
},
|
||
{
|
||
"n": "onSubmit",
|
||
"t": "() => void",
|
||
"k": 1,
|
||
"d": "全部字段校验通过后的提交回调"
|
||
},
|
||
{
|
||
"n": "(formItem)label",
|
||
"t": "string",
|
||
"r": 1,
|
||
"d": "字段标签"
|
||
},
|
||
{
|
||
"n": "(formItem)value",
|
||
"t": "Signal<string>",
|
||
"r": 1,
|
||
"d": "字段值信号,校验数据源"
|
||
},
|
||
{
|
||
"n": "(formItem)required",
|
||
"t": "boolean",
|
||
"d": "必填:显示红星并自动追加非空规则"
|
||
},
|
||
{
|
||
"n": "(formItem)rules",
|
||
"t": "FormRule[]",
|
||
"d": "校验规则:required / min / max / pattern / validator,按序执行取首个失败"
|
||
},
|
||
{
|
||
"n": "(formItem)validateOn",
|
||
"t": "'input' | 'blur' | 'submit'",
|
||
"d": "校验时机;缺省 blur(输入时自动清已报错误)",
|
||
"df": "blur"
|
||
}
|
||
],
|
||
"example": "const name = signal(''); const f = form({ onSubmit: submit }, [formItem({ label: '用户名', required: true, value: name, rules: [{ min: 2, max: 12 }] }, textField({ value: name }))])",
|
||
"steps": [
|
||
"为每个字段创建 signal 与控件,如 const name = signal(''); textField({ value: name })",
|
||
"用 formItem 包住控件:formItem({ label, required, value, rules }, control),返回 { el, validate } 句柄",
|
||
"把句柄数组交给 form:form({ onSubmit }, items),form 渲染全部字段 + 提交/重置按钮",
|
||
"提交时逐项校验:全过触发 onSubmit;有错则标红控件、显示错误文案并聚焦首个出错项",
|
||
"规则语义:required 非空(trim)、min/max 长度、pattern 正则、validator 自定义(true 通过 / 字符串为错误)",
|
||
"非必填字段为空时跳过其余规则;Enter 键触发表单原生 submit(已拦截走校验流程)",
|
||
"错误态覆盖包裹式控件:标红作用于控件根与内部原生控件(含自绘 select 的触发器),并同步 aria-invalid,读屏与视觉一致",
|
||
"触发时机用 input / change / focusout(均会冒泡),因此 checkbox / select / 单选组这类包裹式控件同样能失焦校验"
|
||
]
|
||
},
|
||
{
|
||
"id": "dataTable",
|
||
"title": "数据表格 DataTable",
|
||
"demo": "sec-table",
|
||
"props": [
|
||
{
|
||
"n": "data",
|
||
"t": "T[]",
|
||
"r": 1,
|
||
"d": "全量行数据,每行须含 id 字段作 rowKey"
|
||
},
|
||
{
|
||
"n": "columns",
|
||
"t": "ColumnDef<T>[]",
|
||
"r": 1,
|
||
"d": "列定义:内核字段 { key, header?, sortable?, width? } + 皮肤字段 { align?, format? };width 数字为固定像素,'flex' 自适应"
|
||
},
|
||
{
|
||
"n": "filterKey",
|
||
"t": "string",
|
||
"d": "工具栏筛选的列;缺省取第一列"
|
||
},
|
||
{
|
||
"n": "pageSize",
|
||
"t": "number",
|
||
"d": "每页行数;缺省 5",
|
||
"df": "5"
|
||
},
|
||
{
|
||
"n": "selectable",
|
||
"t": "boolean",
|
||
"d": "启用行选择列:全选三态(含半选)、行 checkbox、已选计数;缺省 false",
|
||
"df": "false"
|
||
},
|
||
{
|
||
"n": "page",
|
||
"t": "Signal<number>",
|
||
"d": "受控页码信号:与内核分页双向同步,传同一个信号给独立 pagination 组件即可联动"
|
||
},
|
||
{
|
||
"n": "loading",
|
||
"t": "boolean | Signal<boolean>",
|
||
"d": "加载态:为真时数据行换成骨架行(行数随 pageSize),筛选输入与翻页按钮临时禁用,容器带 aria-busy"
|
||
},
|
||
{
|
||
"n": "selected",
|
||
"t": "Signal<RowKey[]>",
|
||
"d": "受控选中行信号:与内核选择双向同步(内容比较,不来回派发),供批量操作读取/改写"
|
||
}
|
||
],
|
||
"example": "dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓名', sortable: true }], pageSize: 5 })",
|
||
"steps": [
|
||
"准备行数据,确保每行有唯一 id(跨页选择与刷新不丢行靠它)",
|
||
"定义 columns:sortable: true 的列表头可点击排序(升 → 降 → 取消循环),标记箭头 ↑↓↕",
|
||
"列展示细节用皮肤字段:align 控制表头与单元格对齐,format(value, row) 返回纯文本(走 textContent,不需要转义)",
|
||
"列宽用内核字段 width:数字(像素)固定该列,'flex' 或不设则按内容自适应",
|
||
"selectable: true 开启行选择:表头全选框带 indeterminate 半选态,工具栏显示已选计数",
|
||
"选中行用低视觉比重样式(淡色底 + 弱化文字),选择状态存 rowKey,跨页不丢失",
|
||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||
"数据在途时传 loading(布尔或信号):表格体换成骨架行、筛选与翻页禁用,返回后置回 false 即恢复",
|
||
"需要独立分页器联动时传 page 信号:const page = signal(1),dataTable({ page }) 与 pagination({ page }) 共用",
|
||
"需要批量操作时传 selected 信号:内部勾选实时写回,外部置空或赋值即同步整表(跨页保留,按 rowKey 存)"
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|