608 lines
22 KiB
Plaintext
608 lines
22 KiB
Plaintext
# @ui-arch 组件库 Agent 文档(无图形版)
|
||
|
||
> 自动生成于 2026-10-23T07:52:40.603Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||
|
||
## 快速上手
|
||
|
||
### @ui-arch/frame
|
||
|
||
1. 引入:import { signal, computed, effect, h, mount } from '@ui-arch/frame'
|
||
2. 声明状态:const count = signal(0);无参调用读值 count(),传参写值 count(1)
|
||
3. 渲染视图:mount('#app', () => h('div', null, () => `count = ${count()}`))——函数型子节点即响应式文本
|
||
4. 绑定事件:props 里 on 开头且值为函数的键(onClick 等)自动 addEventListener
|
||
5. 派生数据:const double = computed(() => count() * 2),视图里直接调用 double(),依赖自动追踪
|
||
6. 列表渲染:renderList(tbody, () => rows.map(r => h('tr', null, r.name))),信号变化整体替换子节点
|
||
|
||
### @ui-arch/table-core
|
||
|
||
1. 创建实例:const table = createTable({ data, columns, rowKey: 'id', plugins: [filterPlugin(), sortPlugin(), paginationPlugin()] })
|
||
2. 取派生数据:table.getVisibleRows() 返回 { rows, total };total 语义固定 = 筛选后、分页前的行数
|
||
3. 变更状态:只能 dispatch action,如 table.dispatch({ type: 'toggleSort', key: 'name' });状态不可变
|
||
4. 订阅刷新:table.subscribe(fn),fn 里重新 getVisibleRows() 并交给渲染层
|
||
5. 分页信息:api.getPageInfo() 返回 { page, pageSize, totalPages };越界页码自动钳制
|
||
6. 扩展能力:实现 TablePlugin(derive / patchState / api 三钩子)传入 plugins 即插入管线
|
||
|
||
### @ui-arch/tokens
|
||
|
||
1. 引入:在应用入口 import '@ui-arch/tokens/tokens.css'
|
||
2. 消费:组件样式一律 var(--ua-color-accent) 这类变量,不写死色值
|
||
3. 暗色:根元素设 data-theme=dark,变量值自动切换
|
||
4. 扩展:新令牌先同时加进 tokens.css 与 tokens.json,再重新生成文档站
|
||
|
||
### @ui-arch/ui
|
||
|
||
1. 安装依赖:pnpm add @ui-arch/ui @ui-arch/frame(workspace 内自动链接)
|
||
2. 引入样式:在应用入口 import '@ui-arch/ui/ui.css',暗色主题在根元素设 data-theme='dark'
|
||
3. 创建状态:import { signal } from '@ui-arch/frame',如 const name = signal('')
|
||
4. 调用组件:const el = textField({ value: name }),把 el 挂到你的容器或配合 h() 组合
|
||
5. 读写状态:name() 读、name('张三') 写,界面自动同步,无需手动操作 DOM
|
||
|
||
## @ui-arch/ui(skin-dom)v0.1.0
|
||
|
||
19 个 DOM 组件,统一用法:组件是普通函数,传入 props 返回 DOM 节点;需要状态时先创建 signal 再双向绑定。引入 CSS:import '@ui-arch/ui/ui.css'(内部已消费 tokens)。
|
||
|
||
### button — 按钮 Button
|
||
|
||
参数:
|
||
|
||
- label(必填):string —— 按钮文案
|
||
- variant:'primary' | 'ghost' | 'danger' —— 视觉强度;缺省 primary
|
||
- onClick(回调):() => void —— 点击回调
|
||
|
||
示例:
|
||
|
||
```
|
||
button({ label: '提交', variant: 'primary', onClick: () => console.log('clicked') })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 确定语义强度:主操作用 primary(默认),次要操作用 ghost,危险操作用 danger
|
||
2. 绑定 onClick 回调处理点击逻辑
|
||
3. 需要禁用态时自行在回调首行卫语句判断,或外层包条件渲染
|
||
|
||
现场演示:apps/docs/demo.html#sec-counter
|
||
|
||
### textField — 文本输入 TextField
|
||
|
||
参数:
|
||
|
||
- value:Signal<string> —— 双向绑定信号:输入写回信号,信号变化写回输入框
|
||
- placeholder:string —— 占位文案
|
||
- onInput(回调):(value: string) => void —— 输入回调,每次按键触发
|
||
|
||
示例:
|
||
|
||
```
|
||
const name = signal(''); const el = textField({ value: name, placeholder: '输入名字…', onInput: (v) => console.log(v) })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 先用 signal('') 创建字符串信号
|
||
2. 传入 value 完成双向绑定:用户输入自动写回,外部赋值自动回显
|
||
3. 在任意响应式位置用 name() 读取最新值,如 () => `你好,${name()}`
|
||
|
||
现场演示:apps/docs/demo.html#sec-bind
|
||
|
||
### textarea — 多行输入 Textarea
|
||
|
||
参数:
|
||
|
||
- value:Signal<string> —— 双向绑定信号
|
||
- rows:number —— 初始行数;缺省 3
|
||
- placeholder:string —— 占位文案
|
||
- onInput(回调):(value: string) => void —— 输入回调
|
||
|
||
示例:
|
||
|
||
```
|
||
const bio = signal(''); textarea({ value: bio, rows: 4, placeholder: '一句话介绍…' })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建信号并传入 value
|
||
2. 用 rows 控制初始高度,用户可纵向拉伸
|
||
3. 字数统计等派生逻辑直接在响应式文本里读 bio().length
|
||
|
||
现场演示:apps/docs/demo.html#sec-form
|
||
|
||
### checkbox — 复选框 Checkbox
|
||
|
||
参数:
|
||
|
||
- checked:Signal<boolean> —— 勾选状态信号,双向绑定
|
||
- label:string —— 右侧文案;缺省只渲染勾选框
|
||
- onChange(回调):(checked: boolean) => void —— 变更回调
|
||
|
||
示例:
|
||
|
||
```
|
||
const agreed = signal(false); checkbox({ label: '同意条款', checked: agreed, onChange: (v) => console.log(v) })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建布尔信号 agreed = signal(false)
|
||
2. 传入 checked 与 label,勾选即写回信号
|
||
3. 表单提交前用 agreed() 判断是否勾选
|
||
|
||
现场演示:apps/docs/demo.html#sec-form
|
||
|
||
### switchButton — 开关 Switch
|
||
|
||
参数:
|
||
|
||
- checked:Signal<boolean> —— 开关状态信号,双向绑定
|
||
- label:string —— 左侧文案
|
||
- onChange(回调):(checked: boolean) => void —— 变更回调
|
||
|
||
示例:
|
||
|
||
```
|
||
const night = signal(true); switchButton({ label: '夜间模式', checked: night })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建布尔信号并传入 checked
|
||
2. 轨道与滑块的动画由 CSS 完成,无需干预
|
||
3. 状态变化在 onChange 里做副作用(如切换主题)
|
||
|
||
现场演示:apps/docs/demo.html#sec-form
|
||
|
||
### select — 下拉选择 Select(自绘弹层)
|
||
|
||
参数:
|
||
|
||
- options(必填):OptionItem[] —— 选项列表,每项 { value, label }
|
||
- value:Signal<string> —— 选中值信号,双向绑定
|
||
- placeholder:string —— 未选中时触发器显示的占位文案
|
||
- onChange(回调):(value: string) => void —— 选中回调
|
||
|
||
示例:
|
||
|
||
```
|
||
const city = signal(''); select({ options: [{ value: 'bj', label: '北京' }], value: city, placeholder: '选择城市…' })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 准备 options 数组,value 是提交用值、label 是展示文案
|
||
2. 创建信号并传入 value;未传时组件内部自持状态
|
||
3. 点击触发器展开弹层,点选项写回信号并收起;点外部或按 Esc 也会收起
|
||
4. 选中项在弹层中用淡色弱化标记,不抢视觉焦点
|
||
|
||
现场演示:apps/docs/demo.html#sec-form
|
||
|
||
### radioGroup — 单选组 RadioGroup
|
||
|
||
参数:
|
||
|
||
- options(必填):OptionItem[] —— 选项列表
|
||
- value:Signal<string> —— 选中值信号,双向绑定
|
||
- onChange(回调):(value: string) => void —— 变更回调
|
||
|
||
示例:
|
||
|
||
```
|
||
const size = signal('m'); radioGroup({ options: [{ value: 's', label: '小' }, { value: 'm', label: '中' }], value: size })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建字符串信号,初值设为默认选项的 value
|
||
2. 传入 options 与 value,组内自动互斥
|
||
3. 读取 size() 获取当前选中值
|
||
|
||
现场演示:apps/docs/demo.html#sec-form
|
||
|
||
### card — 卡片 Card
|
||
|
||
参数:
|
||
|
||
- title:string —— 标题;缺省不渲染标题行
|
||
- ...children:unknown[] —— 任意子节点:字符串 / DOM / 响应式函数
|
||
|
||
示例:
|
||
|
||
```
|
||
card({ title: '用户表' }, dataTable({ data, columns }))
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. card 是容器组件:第一个参数是 props,其余参数是任意子节点
|
||
2. 传 title 显示标题行,否则只有内容区
|
||
3. 子节点可以混合字符串、DOM 节点与响应式函数
|
||
|
||
现场演示:apps/docs/demo.html#sec-card
|
||
|
||
### badge — 徽标 Badge
|
||
|
||
参数:
|
||
|
||
- label(必填):string —— 徽标文案
|
||
- variant:'default' | 'success' | 'warning' | 'danger' —— 语义色;缺省 default
|
||
|
||
示例:
|
||
|
||
```
|
||
badge({ label: '成功', variant: 'success' })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 选择语义色:default 中性、success 成功、warning 警告、danger 危险
|
||
2. 传入 label 即可,纯展示组件无状态
|
||
|
||
现场演示:apps/docs/demo.html#sec-feedback
|
||
|
||
### alert — 提示条 Alert
|
||
|
||
参数:
|
||
|
||
- message(必填):string —— 提示内容
|
||
- variant:'info' | 'success' | 'warning' | 'danger' —— 语义色;缺省 info
|
||
|
||
示例:
|
||
|
||
```
|
||
alert({ message: '操作可能存在风险', variant: 'warning' })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 按信息级别选 variant:info 提示、success 成功、warning 警告、danger 错误
|
||
2. 传入 message 即可,入场自带下滑动画
|
||
|
||
现场演示:apps/docs/demo.html#sec-feedback
|
||
|
||
### skeleton — 骨架屏 Skeleton
|
||
|
||
参数:
|
||
|
||
- variant:'text' | 'rect' | 'circle' —— 占位形状;缺省 rect(整块矩形)
|
||
- rows:number —— text 形状的行数;缺省 3,末行自动缩短模拟段落
|
||
|
||
示例:
|
||
|
||
```
|
||
skeleton({ variant: 'text', rows: 3 }); skeleton({ variant: 'circle' }); skeleton({ variant: 'rect' })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 数据加载期间用 skeleton 顶替真实内容,加载完成后整体替换
|
||
2. 文本段落用 variant: 'text' + rows 控制行数,头像用 'circle',卡片/图片区域用 'rect'
|
||
3. 占位块自带扫光动画,reduced-motion 用户自动静态化为纯灰块
|
||
4. 组合布局:skeleton 是普通 DOM,可放进 card / row 等任意容器
|
||
|
||
现场演示:apps/docs/demo.html#sec-skeleton
|
||
|
||
### toast — 消息提示 Toast
|
||
|
||
参数:
|
||
|
||
- message(必填):string —— 提示文案
|
||
- duration:number —— 自动消失毫秒;缺省 3000
|
||
- variant:'info' | 'success' | 'warning' | 'danger' —— 语义色;缺省 info(toast.error 对应 danger)
|
||
|
||
示例:
|
||
|
||
```
|
||
toast.success('保存成功'); toast.error('网络请求失败', 5000)
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 直接调用语义工厂:toast.info / success / warning / error(message, duration?),无需先建容器
|
||
2. 不传 duration 时默认停留 3 秒后自动淡出并移除节点
|
||
3. 多条消息在右上角自动纵向堆叠,互不遮挡
|
||
4. 需要完整入参(含 variant)时用 showToast(props);组件挂载容器由内部懒创建,样式随 ui.css 一起引入
|
||
|
||
现场演示:apps/docs/demo.html#sec-toast
|
||
|
||
### tooltip — 悬浮提示 Tooltip
|
||
|
||
参数:
|
||
|
||
- content(必填):string —— 提示文案(纯文本)
|
||
- placement:'top' | 'bottom' —— 气泡方位;缺省 top(触发器上方)
|
||
- delay:number —— 出场延迟毫秒;缺省 150,传 0 立即显示
|
||
- trigger(必填):HTMLElement —— 第二个参数:被包裹的触发器元素(按钮 / 输入框等任意 DOM)
|
||
|
||
示例:
|
||
|
||
```
|
||
tooltip({ content: '保存后立即生效' }, button({ label: '保存', onClick: save }))
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 先创建触发器元素,如 const btn = button({ label: '保存' })
|
||
2. 用 tooltip(props, trigger) 包一层:返回带气泡的包裹元素,原触发器仍是独立节点
|
||
3. 鼠标移入或键盘聚焦约 150ms 后出场,移出 / 失焦立即收起;按 Esc 可立刻关闭
|
||
4. 气泡默认在上方,空间不足或需要避让时传 placement: 'bottom'
|
||
5. 气泡 pointer-events: none 不抢指针;判读依赖 aria-describedby + role='tooltip',读屏可读
|
||
6. 只做展示:不要在气泡里放可点击元素,需要交互请用 modal 或自绘弹层
|
||
|
||
现场演示:apps/docs/demo.html#sec-tooltip
|
||
|
||
### spinner — 加载指示器 Spinner
|
||
|
||
参数:
|
||
|
||
- size:number —— 直径像素;缺省 18
|
||
|
||
示例:
|
||
|
||
```
|
||
spinner(); spinner({ size: 26 })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 数据加载时插入 spinner(),加载完成移除
|
||
2. 用 size 匹配上下文尺寸(按钮内用小号,整页 loading 用大号)
|
||
|
||
现场演示:apps/docs/demo.html#sec-feedback
|
||
|
||
### progress — 进度条 Progress
|
||
|
||
参数:
|
||
|
||
- value(必填):Signal<number> —— 进度 0-100 信号,变化自动平滑过渡
|
||
- showText:boolean —— 是否显示百分比文字;缺省 true
|
||
|
||
示例:
|
||
|
||
```
|
||
const pct = signal(0); progress({ value: pct }); setInterval(() => pct((pct() + 5) % 105), 400)
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建数值信号 pct = signal(0),范围 0-100(越界自动钳制)
|
||
2. 传入 value,填充宽度与百分比文字随信号平滑过渡
|
||
3. 进行中填充带流动条纹,到 100% 自动变 success 色并停止条纹
|
||
4. 不需要百分比文字时传 showText: false
|
||
|
||
现场演示:apps/docs/demo.html#sec-feedback
|
||
|
||
### tabs — 标签页 Tabs
|
||
|
||
参数:
|
||
|
||
- tabs(必填):OptionItem[] —— 页签列表,每项 { value, label }
|
||
- active:Signal<string> —— 当前激活页签 value 信号,双向绑定
|
||
- onChange(回调):(value: string) => void —— 切换回调
|
||
|
||
示例:
|
||
|
||
```
|
||
const tab = signal('a'); tabs({ tabs: [{ value: 'a', label: '概览' }, { value: 'b', label: '明细', disabled: true }], active: tab })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建信号 tab = signal('a'),初值为默认页签
|
||
2. tabs 只渲染页签头;页签内容用响应式函数按信号切换,如 () => tab() === 'a' ? panelA : panelB
|
||
3. 点击或方向键(←→ 环形)切换,滑动指示条自动跟随;disabled: true 的页签置灰不可点
|
||
4. 键盘可访问:Tab 聚焦激活页签,←→ 在启用页签间环形移动
|
||
|
||
现场演示:apps/docs/demo.html#sec-tabs-modal
|
||
|
||
### modal — 弹窗 Modal
|
||
|
||
参数:
|
||
|
||
- open(必填):Signal<boolean> —— 开关信号:true 显示 / false 隐藏
|
||
- title(必填):string —— 标题
|
||
- onClose(回调):() => void —— 关闭回调(点遮罩、× 或 Esc 触发)
|
||
- ...children:unknown[] —— 弹窗内容子节点
|
||
|
||
示例:
|
||
|
||
```
|
||
const open = signal(false); modal({ title: '确认操作', open, onClose: () => open(false) }, h('p', null, '内容'))
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 创建布尔信号 open = signal(false),弹窗初始隐藏
|
||
2. 把 open 传给 modal,其余参数为弹窗内容子节点
|
||
3. 打开:open(true);关闭:open(false),点遮罩或 × 会自动写回 false
|
||
4. 入场自带遮罩淡入 + 弹窗上浮动画
|
||
|
||
现场演示:apps/docs/demo.html#sec-tabs-modal
|
||
|
||
### form — 表单 Form / 表单字段 FormItem
|
||
|
||
参数:
|
||
|
||
- layout:'vertical' | 'horizontal' —— 布局方向;缺省 vertical(horizontal 为标签左置)
|
||
- submitText:string —— 提交按钮文案;缺省「提交」
|
||
- resetText:string —— 重置按钮文案;缺省不渲染
|
||
- onSubmit(回调):() => void —— 全部字段校验通过后的提交回调
|
||
- (formItem)label(必填):string —— 字段标签
|
||
- (formItem)value(必填):Signal<string> —— 字段值信号,校验数据源
|
||
- (formItem)required:boolean —— 必填:显示红星并自动追加非空规则
|
||
- (formItem)rules:FormRule[] —— 校验规则:required / min / max / pattern / validator,按序执行取首个失败
|
||
- (formItem)validateOn:'input' | 'blur' | 'submit' —— 校验时机;缺省 blur(输入时自动清已报错误)
|
||
|
||
示例:
|
||
|
||
```
|
||
const name = signal(''); const f = form({ onSubmit: submit }, [formItem({ label: '用户名', required: true, value: name, rules: [{ min: 2, max: 12 }] }, textField({ value: name }))])
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 为每个字段创建 signal 与控件,如 const name = signal(''); textField({ value: name })
|
||
2. 用 formItem 包住控件:formItem({ label, required, value, rules }, control),返回 { el, validate } 句柄
|
||
3. 把句柄数组交给 form:form({ onSubmit }, items),form 渲染全部字段 + 提交/重置按钮
|
||
4. 提交时逐项校验:全过触发 onSubmit;有错则标红控件、显示错误文案并聚焦首个出错项
|
||
5. 规则语义:required 非空(trim)、min/max 长度、pattern 正则、validator 自定义(true 通过 / 字符串为错误)
|
||
6. 非必填字段为空时跳过其余规则;Enter 键触发表单原生 submit(已拦截走校验流程)
|
||
|
||
现场演示:apps/docs/demo.html#sec-formlab
|
||
|
||
### dataTable — 数据表格 DataTable
|
||
|
||
参数:
|
||
|
||
- data(必填):T[] —— 全量行数据,每行须含 id 字段作 rowKey
|
||
- columns(必填):ColumnDef<T>[] —— 列定义:{ key, header?, sortable? }
|
||
- filterKey:string —— 工具栏筛选的列;缺省取第一列
|
||
- pageSize:number —— 每页行数;缺省 5
|
||
- selectable:boolean —— 启用行选择列:全选三态(含半选)、行 checkbox、已选计数;缺省 false
|
||
|
||
示例:
|
||
|
||
```
|
||
dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓名', sortable: true }], pageSize: 5 })
|
||
```
|
||
|
||
手把手:
|
||
|
||
1. 准备行数据,确保每行有唯一 id(跨页选择与刷新不丢行靠它)
|
||
2. 定义 columns:sortable: true 的列表头可点击排序(升 → 降 → 取消循环),标记箭头 ↑↓↕
|
||
3. selectable: true 开启行选择:表头全选框带 indeterminate 半选态,工具栏显示已选计数
|
||
4. 选中行用低视觉比重样式(淡色底 + 弱化文字),选择状态存 rowKey,跨页不丢失
|
||
5. 工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行
|
||
6. 表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供
|
||
|
||
现场演示:apps/docs/demo.html#sec-table
|
||
|
||
API 速览:
|
||
|
||
- button(props):按钮,variant = primary | ghost | danger
|
||
- textField(props):文本输入,value 信号双向绑定
|
||
- textarea(props):多行输入,value 信号双向绑定
|
||
- checkbox(props):复选框,checked 信号双向绑定
|
||
- switchButton(props):开关,checked 信号双向绑定
|
||
- select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画
|
||
- radioGroup(props):单选组,options + value 信号双向绑定
|
||
- card(props, ...children):卡片容器
|
||
- badge(props):徽标,variant = default | success | warning | danger
|
||
- alert(props):提示条,variant = info | success | warning | danger
|
||
- toast.info/success/warning/error(message, duration?):消息提示工厂,右上角堆叠,默认 3s 自动消失,出入场微动画;showToast(props) 为完整入参版本
|
||
- tooltip(props, trigger):悬浮提示,包裹触发器,hover / focus 延迟 150ms 出场,移出 / 失焦 / Esc 收起
|
||
- skeleton(props):骨架屏占位,variant = text | rect | circle,text 支持 rows 多行,扫光微动画
|
||
- spinner(props):加载指示器,size 控制直径
|
||
- progress(props):进度条,轨道 + 渐变流动填充,value 信号驱动 0-100,满格切 success 色
|
||
- tabs(props):标签页,active 信号双向绑定,滑动指示条 + 方向键环形导航,支持禁用页签
|
||
- modal(props, ...children):弹窗,open 信号驱动显隐,Esc / 遮罩 / × 关闭
|
||
- form(props, items):表单容器,布局 + 聚合校验,全部通过才触发 onSubmit
|
||
- formItem(props, control):表单字段,label + 必填红星 + 规则校验 + 错误区,返回 { el, validate } 句柄
|
||
- dataTable(props):数据表格,粘性表头 / 行选择(全选三态)/ 排序 / 筛选 / 分页 / 空状态,内核为 table-core
|
||
|
||
一行用法:
|
||
|
||
```
|
||
const checked = signal(false); checkbox({ label: '同意', checked }); const open = signal(false); modal({ title: '确认', open }, '内容')
|
||
```
|
||
|
||
约定:
|
||
|
||
- 皮肤不持有业务状态,一律委托 headless 内核或调用方信号
|
||
- 表单类组件统一约定:*Props.value/checked/active 为 Signal 双向绑定,onChange/onInput 为回调
|
||
- 语义色 variant 四档:default|info / success / warning / danger,一律来自令牌,禁止硬编码颜色
|
||
|
||
---
|
||
|
||
## @ui-arch/frame(headless-core)v0.1.0
|
||
|
||
零依赖微框架:组件 = 返回 DOM 的普通函数。signal/effect/computed 管状态,h() 管 DOM,无虚拟 DOM 无生命周期抽象。
|
||
|
||
API 速览:
|
||
|
||
- signal(initial) -> Signal<T>:无参读值并收集依赖,传参写值并触发订阅
|
||
- effect(fn):立即执行并追踪依赖,信号变化自动重跑
|
||
- computed(fn):由信号派生的只读计算值
|
||
- h(tag, props, ...children):hyperscript;on* 绑事件,函数值属性/子节点自动响应式
|
||
- renderList(el, fn):信号变化时整体替换容器子节点
|
||
- mount(target, view):挂载视图
|
||
|
||
一行用法:
|
||
|
||
```
|
||
const count = signal(0); mount('#app', () => h('button', { onClick: () => count(count() + 1) }, () => `count = ${count()}`))
|
||
```
|
||
|
||
约定:
|
||
|
||
- 组件 = 返回 DOM 节点的普通函数,不做类组件与生命周期抽象
|
||
- 跨系统状态(如 table-core)用桥接信号:subscribe 里递增 version 信号
|
||
|
||
---
|
||
|
||
## @ui-arch/table-core(headless-core)v0.1.0
|
||
|
||
Headless 表格内核:不渲染任何 DOM,只管理状态与派生。任何渲染层通过 getVisibleRows() 拿行模型,配 subscribe() 刷新。
|
||
|
||
API 速览:
|
||
|
||
- createTable(options) -> TableInstance: create headless table instance
|
||
- sortPlugin(options?) -> multi-column sorting plugin (asc -> desc -> off cycle)
|
||
- filterPlugin(options?) -> column filter plugin (default substring match, custom predicate supported)
|
||
- paginationPlugin() -> client-side pagination with page clamping, exposes setPage/nextPage/prevPage/getPageInfo
|
||
- selectionPlugin() -> rowKey-based selection, exposes selectAllVisible
|
||
|
||
一行用法:
|
||
|
||
```
|
||
const table = createTable({ data, columns, rowKey: 'id', plugins: [filterPlugin(), sortPlugin(), paginationPlugin()], initialState: { pagination: { page: 1, pageSize: 20 } } }); table.dispatch({ type: 'toggleSort', key: 'name' }); table.getVisibleRows()
|
||
```
|
||
|
||
约定:
|
||
|
||
- selection/expanded must store rowKey, never row index
|
||
- derive pipeline order is fixed: filter -> sort -> paginate
|
||
- actions are the only way to mutate state; state is immutable
|
||
|
||
---
|
||
|
||
## @ui-arch/tokens(design-tokens)v0.1.0
|
||
|
||
设计令牌唯一来源:CSS 变量 --ua-* + 同名 JSON。皮肤只允许消费变量,禁止硬编码颜色;暗色只换值不换名。
|
||
|
||
API 速览:
|
||
|
||
- tokens.css: import '@ui-arch/tokens/tokens.css' once at app root
|
||
- tokens.json: programmatic access for tools and agents
|
||
|
||
一行用法:
|
||
|
||
```
|
||
import '@ui-arch/tokens/tokens.css'; then use var(--ua-color-accent) etc. in any skin package
|
||
```
|
||
|
||
---
|
||
|
||
## 设计令牌(--ua-*)
|
||
|
||
- --ua-color-bg: #ffffff(暗色 #101216)
|
||
- --ua-color-surface: #f6f7f9(暗色 #1a1c22)
|
||
- --ua-color-text: #1c1e21(暗色 #e7e9ec)
|
||
- --ua-color-textMuted: #6b7280(暗色 #888780)
|
||
- --ua-color-accent: #185fa5(暗色 #378add)
|
||
- --ua-color-danger: #a32d2d
|
||
- --ua-color-success: #0f6e56
|
||
|
||
### radius
|
||
|
||
- --ua-radius-sm: 4px
|
||
- --ua-radius-md: 8px
|
||
- --ua-radius-lg: 12px
|
||
|
||
### space
|
||
|
||
- --ua-space-1: 4px
|
||
- --ua-space-2: 8px
|
||
- --ua-space-3: 12px
|
||
- --ua-space-4: 16px
|