weifuwu 0.91.0 → 0.93.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/client/components/index.d.ts +3 -0
- package/dist/client/components/style.css +1 -12219
- package/dist/client/layout/bundle.d.ts +42 -0
- package/dist/client/layout/weifuwu-layout.css +1 -1495
- package/dist/client/vdom/core/protocol.d.ts +62 -7
- package/dist/client/vdom/index.js +3 -3
- package/dist/server/db/http.d.ts +4 -4
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +295 -174
- package/dist/server/response.d.ts +17 -0
- package/docs/client.md +128 -7
- package/docs/layout.md +243 -0
- package/docs/server.md +229 -9
- package/package.json +5 -3
|
@@ -44,3 +44,20 @@ export declare function serverError(message?: string): Response;
|
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
46
|
export declare function redirect(url: string, status?: number): Response;
|
|
47
|
+
/**
|
|
48
|
+
* 错误 → Response(总错误面——HTTP 链(router.onError/默认链)与 route 内
|
|
49
|
+
* catch 同语义——DbError/HttpError 映射单源)。
|
|
50
|
+
*
|
|
51
|
+
* 双层语义(有意分层——文档契约):
|
|
52
|
+
* - **链面(未捕获)**:普通 Error → 500(Internal Server Error——意外错误
|
|
53
|
+
* 诚实现形不泄漏——router.handleError 默认链消费);DbError/ValidationError
|
|
54
|
+
* → 400/409(orm 错误不该 500)
|
|
55
|
+
* - **route 内 catch(已知业务)**:普通 Error → 400(业务守卫/校验——
|
|
56
|
+
* 「我知道这是什么错」→ errorResponse 显式调用)
|
|
57
|
+
* - HttpError:双面一致(status 权威——403/404/409 同输出)
|
|
58
|
+
*
|
|
59
|
+
* code 面(`{ error, code }`——前端可 switch 而非解析 message 字符串):
|
|
60
|
+
* ValidationError → 'validation' · DbError 23505 → 'conflict' ·
|
|
61
|
+
* DbError.kind → kind · HttpError/普通 Error → 无 code(status 已是语义)。
|
|
62
|
+
*/
|
|
63
|
+
export declare function errorResponse(e: unknown, status?: number): Response;
|
package/docs/client.md
CHANGED
|
@@ -56,21 +56,57 @@ app.router(Router())
|
|
|
56
56
|
## 3. 设计语言
|
|
57
57
|
|
|
58
58
|
微流明(Whisper Luminance):中性色主导、品牌色点睛、动效短促有目的(120–300ms)、
|
|
59
|
-
1px 边界即结构。**Token 即规范**——`src/client/layout/
|
|
60
|
-
色阶/排版/动效/圆角/阴影/z-index
|
|
59
|
+
1px 边界即结构。**Token 即规范**——`src/client/layout/_tokens.css`(178 token:
|
|
60
|
+
色阶/排版/动效/圆角/阴影/z-index;`_dark.css` 暗色覆写 · `_presets.css` 紧凑预设覆写)
|
|
61
|
+
——组件只引用 token、零硬编码(audit 强制)。
|
|
62
|
+
|
|
63
|
+
**token 两面纪律**(layout-inventory L10/L11 哨兵):
|
|
64
|
+
|
|
65
|
+
- **断点单源**:`--wf-bp-sm/md/lg/xl` = 640/768/1024/1280——CSS 媒体查询语法不能
|
|
66
|
+
`var()`,故 token 作**审计白名单源**:合法字面量只有两形态 `V`(`min-width`)与
|
|
67
|
+
`V - 0.02`(`max-width`)——二者无缝对接(旧碎片:组件面 `639px`/`767px` vs
|
|
68
|
+
layout 面 `767.98px`——767.00–767.98 区间两侧规则同时失配)
|
|
69
|
+
- **死面 = 0(登记制)**:token 声明必须有消费证据(`var()` / TS 字面)——零消费即删,
|
|
70
|
+
结构性不可消费的(bp-* 机制源 · gap-2xl 标尺完整性)逐条登记理由;反向哨兵:
|
|
71
|
+
登记项一旦有消费者即需移出(防登记表腐化)
|
|
72
|
+
- **双标尺(定案)**:`--wf-gap-*` **派生**自 `--wf-space-*`(紧一档:gap-md = space 裸档
|
|
73
|
+
= 12px · gap-lg = space-md)。容器内元素间距 < 控件内边距是有意的密度设计,**不是**
|
|
74
|
+
同名不同值的命名事故——关系入代码(L13 登记 + 值冻结),预设只覆写 space 标尺
|
|
75
|
+
(gap 自动跟随)
|
|
76
|
+
- **同值双名(L12)**:同主题文件内值全等且名为「限定词插入」形态(`shadow` ⊂
|
|
77
|
+
`surface-shadow`)= 历史双名 → 必须 `var()` 单源(语义名保留、值改引用);
|
|
78
|
+
跨域巧合(motion-sm 4px ≡ overlay-blur 4px · 240px/200px 三胞胎)**判负不耦合**
|
|
79
|
+
(耦合即隐形爆炸半径)
|
|
80
|
+
- **px 字面量(L14)**:layout 类文件只允许登记白名单内的结构魔数(44px 命中区 ·
|
|
81
|
+
999px 胶囊 · 1px 发丝走 `--wf-border-width` · 2px/4px bleed 对 · 32px 视口内缩 ·
|
|
82
|
+
2px hover 微抬升)——新增字面量必须 token 化或登记
|
|
61
83
|
|
|
62
84
|
品牌换色 = 改 seed 一个值;预设主题 = `data-theme` 一个属性(minimal/dark)。
|
|
63
85
|
|
|
64
86
|
## 4. 布局系统
|
|
65
87
|
|
|
66
|
-
`src/client/layout/`——
|
|
88
|
+
`src/client/layout/`——50 原语(`_*.css`)+ 98 工具 + 2 内部,全部 `wf-` 前缀;
|
|
89
|
+
**装配单源**:四处管线(build 产物 / showcase dev / 场景 dev / `ctx.ui.css`)共用
|
|
90
|
+
`bundle.ts`——层序单源(D4 审计比对);**发布产物 minify**(esbuild——见文末载荷面):
|
|
67
91
|
|
|
68
92
|
- **原语**:`wf-stack` / `wf-row` / `wf-grid` / `wf-center` / `wf-card-surface` / `wf-divider`
|
|
69
93
|
- **工具**:`wf-padding` / `wf-margin` / `wf-text-*` / `wf-bg-*` / `wf-hidden`
|
|
70
|
-
- **命名规则**:三类词根 +
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
94
|
+
- **命名规则**:三类词根 + 三后缀(完整词根表 = **机器生成** `docs/layout.md`:类清单/断点表/
|
|
95
|
+
钩子表/标尺派生/零消费公共面示例——与 `layout-inventory` 哨兵同源,改布局源码后
|
|
96
|
+
`node scripts/layout-reference.mjs` 再生成;L15 校验漂移即红)
|
|
97
|
+
|
|
98
|
+
零值形态唯一(`none` 归一)· 对齐域禁方向词 · 双名歼灭 · 零值档位矩阵(取消面缺口登记)·
|
|
99
|
+
冲突矩阵(同属性不同值对的同元素共用逐对登记胜者+胜因)· 层叠机制锁定(层序/`:where()`/
|
|
100
|
+
`!important` 白名单/`@property` 钩子注册)· 断点与 token 单源 · token 双名歼灭 ·
|
|
101
|
+
间距标尺派生登记 · px 字面量白名单——layout-inventory **20 断言**锁定;
|
|
102
|
+
层叠语义的浏览器计算值读数见场景层 `e2e-layout-semantics.test.ts`。
|
|
103
|
+
|
|
104
|
+
**载荷面(W6 minify)**:dist 发布产物 `weifuwu-layout.css` **28.1K**(gzip 5.7K · brotli 5.1K)·
|
|
105
|
+
`weifuwu/components/style.css` **220.9K**(gzip 29.4K · brotli 24.3K)——esbuild minify(
|
|
106
|
+
`build.mjs` 实装:`@layer`/`@property`/`@supports`/转义类名全保留,注释全剥离);
|
|
107
|
+
**无组件应用只引 `weifuwu/layout`**(28.1K / br 5.1K——独立面,零组件 CSS 成本)。
|
|
108
|
+
按需子集(per-component 子路径 / purge)**判负**:动态类名漏删风险 + 构建期改造成本
|
|
109
|
+
+ br 后 24.3K 非瓶颈——推翻条件:真实应用首屏 CSS 成为 LCP 阻塞的实测数据。
|
|
74
110
|
|
|
75
111
|
## 5. 组件编写规范(唯一入口)
|
|
76
112
|
|
|
@@ -89,6 +125,10 @@ app.router(Router())
|
|
|
89
125
|
回调/类函数属性差异**不触发**(比较器自有豁免权——如 CodeEditor 忽略 onChange
|
|
90
126
|
闭包引用)。默认不挂 = 行为完全不变。典型:CodeEditor(value/lang/rows/readOnly
|
|
91
127
|
比较——高频输入页面零 diff 扰动)
|
|
128
|
+
**页面级范式(web W3 试点——AgentGrid 先例)**:列表区独立成组件 +
|
|
129
|
+
`shouldRender` 比较**数据引用**(`agents` 数组未变 = 输入键击不重渲列表段——
|
|
130
|
+
高频输入页的「静态邻居」零 diff);回调经闭包(onDm/onRemove 豁免——
|
|
131
|
+
CodeEditor 同款);单消费者页内组件(不违反「>1 消费者入库」——判负登记)
|
|
92
132
|
|
|
93
133
|
### 5.2 三件套
|
|
94
134
|
|
|
@@ -112,6 +152,32 @@ props camelCase · **`className=`(组件 props)`class=`(DOM 元素)** ·
|
|
|
112
152
|
**状态变体类必须有规则或 `:where(.wf-x) {}` 显式声明**(L3 已扩围组件源码——未定义立即红)·
|
|
113
153
|
动效 `--wf-dur-*`/`--wf-ease-*` · transition 含 visibility(隐藏不可 Tab 聚焦)
|
|
114
154
|
|
|
155
|
+
**组件 px 四纪律(C1 哨兵强制——`contract/components-px.test.ts` 四桶登记制)**:
|
|
156
|
+
|
|
157
|
+
1. **间距走标尺**:padding/margin/gap 的 4/8/12/16/24/32px →
|
|
158
|
+
`var(--wf-space-*)`/`var(--wf-gap-*)`(**任一档位值字面量 = 红**——含 var 混合声明
|
|
159
|
+
`padding: 8px var(--wf-x)` 同样适用——半 token 禁止;档位外值 = 结构桶登记制)
|
|
160
|
+
2. **边框宽走发丝 token**:`border[N]: 1px solid/dashed …` → `var(--wf-border-width)`
|
|
161
|
+
(色可走 var/currentColor/transparent——hex 已锁 0;**非 1px 宽 = 强调边框**——无 token 面登记制)
|
|
162
|
+
3. **结构值登记制**:非档位 px(结构尺寸/魔数——height/width/min-*/outline/box-shadow 偏移/
|
|
163
|
+
44px 命中区/z-index:1 等)→ `scripts/components-px-whitelist.json` structural/zIndex 桶
|
|
164
|
+
**登记 + 理由**(新增未登记 = 红 · 处理完未移出 = 幽灵红)
|
|
165
|
+
4. **豁免面**:派生表达式(calc/env/min/max/clamp——L13 同款)与 0px 零值形态——非作者手写终值
|
|
166
|
+
|
|
167
|
+
> 紧凑预设语义:**只有走 var() 的组件才跟随缩放**(_presets.css「间距缩一档」——手写=静止=活体缺口)。
|
|
168
|
+
|
|
169
|
+
**C2 扩展纪律(`contract/components-token.test.ts` 三桶——token 消费哨兵)**:
|
|
170
|
+
|
|
171
|
+
5. **文本行高走档**:`line-height` 值 ∈ {1.5, 1.25}(恒等档)→ `var(--wf-line-height)`/
|
|
172
|
+
`var(--wf-line-height-tight)`(近值=红);代码排版 1.6(CodeBlock/DiffView——2 消费者
|
|
173
|
+
<3 升档门——第三消费者出现即升 --wf-line-height-code);豁免面 {1 重置/0/px 图标}
|
|
174
|
+
6. **弹层宽走钩子**:`.wf-popup` 系面板 **禁止手写 max-width**——基类
|
|
175
|
+
`min(var(--wf-popup-max, 480px), calc(100vw - 32px))` 是唯一入口;组件默认宽用
|
|
176
|
+
**回退值**表达(`min(var(--wf-popup-max, 320px), …)`——回退=默认宽);非弹层面板宽
|
|
177
|
+
(命令面板/通知条/工作区)判负登记——`popup-max` 钩子调不动 = 钩子失效面
|
|
178
|
+
7. **token 零消费双分类**:{保留类(色板档/暗色映射档/布局档/断点档——消费形态非
|
|
179
|
+
var() 引用)/真死候选}——新增零消费 token 需登记(消费矩阵哨兵——对齐 L11 组件版)
|
|
180
|
+
|
|
115
181
|
### 5.5 测试二层(覆盖哨兵 ≥2 层)
|
|
116
182
|
|
|
117
183
|
1. **契约 harness**(`<Comp>.test.ts`——mount/render/createTable 命令流断言)
|
|
@@ -142,6 +208,27 @@ style-audit 文件数基线 +1 · 覆盖哨兵跑绿(`scripts/audit-component-
|
|
|
142
208
|
R-03:类名/结构变更**反查测试选择器**(`[class*="..."]` 定位器)·
|
|
143
209
|
行为变化**必带契约测试** · 机制化优先(能进审计不靠记忆)
|
|
144
210
|
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### 6.1 认证接线范式(fullstack W4——onRefresh 时序契约)
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
// uiServe options(v3-main.tsx)——auth 客户端接线(token 双源防线)
|
|
217
|
+
auth: auth({ storage, onAuth: (c) => {...}, onRefresh: async () => {
|
|
218
|
+
// onRefresh 闭包直引(2027-09 教训:间接层 authRef 曾致 401 死循环——
|
|
219
|
+
// refresh 后 token 未更新——闭包直引 source 是唯一的)
|
|
220
|
+
const ok = await api.post('/api/auth/refresh', undefined, { skipAuth: true })
|
|
221
|
+
...
|
|
222
|
+
}})
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- **时序契约**:onRefresh 返回 true 语义 = token 已重写(storage 就绪)——
|
|
226
|
+
false/异常 = 401 踢登录——**未配置 onRefresh → refresh() 恒 false + warn**
|
|
227
|
+
(机制化防线——401 时 console.warn 提示「未接线」——不再静默)
|
|
228
|
+
- 401 → refresh 重试一次(ApiClient 层)→ 仍失败清 token 跳登录(兜底)
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
145
232
|
## 6. 前端架构导论
|
|
146
233
|
|
|
147
234
|
```
|
|
@@ -172,5 +259,39 @@ R-03:类名/结构变更**反查测试选择器**(`[class*="..."]` 定位器
|
|
|
172
259
|
|
|
173
260
|
---
|
|
174
261
|
|
|
262
|
+
### 7.1 页面数据世代(web W1——useAsyncData 首选手册)
|
|
263
|
+
|
|
264
|
+
**为什么迁(v2 段复用实录)**:老世代 `load() + ctx.render()` 在工厂期异步启动
|
|
265
|
+
——v2 段复用语义下**工厂不重跑 → 数据永不刷新**(导航返回/同会话停滞——
|
|
266
|
+
Templates 迁移先例)。**getter 快照 bug(Agents W1 实录)**:`const agents =
|
|
267
|
+
getAgents() ?? []` 在**工厂期**解构 = 渲染用旧快照(state$ 更新后不显示)——
|
|
268
|
+
**必须在 renderFn 内读**(getter 纪律的页面级体现)。
|
|
269
|
+
|
|
270
|
+
**怎么迁(5 行范本)**:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
export const Agents: Component = (_p, ctx) => {
|
|
274
|
+
const [getAgents, reloadAgents] = ctx.ui.useAsyncData(async () => {
|
|
275
|
+
return (await ctx.api.get(`/api/agents`)).agents ?? []
|
|
276
|
+
}, 'agents-page') // 同 key 并发合并 · key 稳定(页面级)
|
|
277
|
+
let qValue = '' // 搜索闭包(getter 纪律)
|
|
278
|
+
return () => {
|
|
279
|
+
const agents = getAgents() ?? [] // 渲染期读最新(不是工厂期!)
|
|
280
|
+
const loading = getAgents() === null // null = loading 态
|
|
281
|
+
return h('ul', {}, agents.map(...))
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**迁移后得到什么**:① 同 key 并发合并(多次挂载 1 次请求)② 竞态取消
|
|
287
|
+
(switchMap——快速搜索乱序响应丢弃)③ 缓存保留(重挂载零请求——导航返回
|
|
288
|
+
瞬时)④ reload 显式刷新(删除/变更后服务器权威)。搜索面:q 闭包 +
|
|
289
|
+
debounce(reload)——触发读最新 q。
|
|
290
|
+
|
|
291
|
+
**哨兵**:`apps/agent-platform/scripts/audit-page-generations.mjs`(async 工厂
|
|
292
|
+
= 红 exit 1——工厂同步契约;老世代标记 = 黄报——迁移进度可见)。
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
175
296
|
> **运行**:`npm run test:client`(428 契约)· `npm run test:scenario`(123 场景)·
|
|
176
297
|
> `npm run test:showcase`(324 组件测试)——全量防线见 AGENTS.md §1。
|
package/docs/layout.md
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# weifuwu/layout 参考
|
|
2
|
+
|
|
3
|
+
> **机器生成**(`scripts/layout-reference.mjs`)——勿手改:改布局源码后跑 `node scripts/layout-reference.mjs`。
|
|
4
|
+
> 单源校对:类清单 = `layout-inventory.mjs inventory()` · 层序 = `bundle.ts LAYER_ORDER` ·
|
|
5
|
+
> 钩子 = `_props.css @property` · 标尺/断点 = `_tokens.css`。计数口径与 README/`docs/client.md` 全等(L6 哨兵)。
|
|
6
|
+
|
|
7
|
+
## 1. 层叠与覆盖规则(L9 机制锁定)
|
|
8
|
+
|
|
9
|
+
- **层序**:@layer `tokens, base, layout, components, utilities`——工具类在 components 之后 = 消费侧显式覆盖恒胜组件样式(旧序相反——W2 修正)
|
|
10
|
+
- **display 族基类**(wf-block/wf-flex/wf-hidden)`:where()` 零优先级——断点变体(@sm/@lg)正常优先级 → 变体恒胜基类(跨文件亦然)
|
|
11
|
+
- **`!important` 白名单**:仅 `prefers-reduced-motion`(无障碍强制)——其余位置禁(变体靠 specificity 胜出)
|
|
12
|
+
- **变量钩子**:`@property inherits:false`(W2)——外层内联赋值不污染子孙原语;syntax `*` 且不写 initial-value(保各原语不同回退值)
|
|
13
|
+
|
|
14
|
+
## 2. 断点(`--wf-bp-*` = 媒体查询白名单单源——L10)
|
|
15
|
+
|
|
16
|
+
| 档 | 值 | 合法媒体查询字面量 |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `--wf-bp-sm` | `640px` | `min-width:640px` / `max-width:639.98px` |
|
|
19
|
+
| `--wf-bp-md` | `768px` | `min-width:768px` / `max-width:767.98px` |
|
|
20
|
+
| `--wf-bp-lg` | `1024px` | `min-width:1024px` / `max-width:1023.98px` |
|
|
21
|
+
| `--wf-bp-xl` | `1280px` | `min-width:1280px` / `max-width:1279.98px` |
|
|
22
|
+
|
|
23
|
+
## 3. 变量钩子(内联覆盖面——`@property` 注册 9 条)
|
|
24
|
+
|
|
25
|
+
| 钩子 | 回退值(layout 内首个消费) | 说明 |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `--wf-gap` | `(无回退——必填钩子)` | 容器间距默认(stack/row/cluster/grid 原语共用) |
|
|
28
|
+
| `--wf-align` | `(无回退——必填钩子)` | 对齐默认(cross-axis) |
|
|
29
|
+
| `--wf-justify` | `(无回退——必填钩子)` | 主轴对齐默认 |
|
|
30
|
+
| `--wf-cols` | `(无回退——必填钩子)` | grid 列模板(grid 原语) |
|
|
31
|
+
| `--wf-max` | `(无回退——必填钩子)` | 容器最大宽(container 原语) |
|
|
32
|
+
| `--wf-w-sm` | `(无回退——必填钩子)` | width-sm 工具类默认 |
|
|
33
|
+
| `--wf-z` | `(无回退——必填钩子)` | z 档位默认 |
|
|
34
|
+
| `--wf-offset` | `(无回退——必填钩子)` | sticky 偏移 |
|
|
35
|
+
| `--wf-popup-max` | `(无回退——必填钩子)` | 弹层最大宽(popup 原语) |
|
|
36
|
+
|
|
37
|
+
## 4. 类清单(inventory 全量——含状态修饰与断点变体)
|
|
38
|
+
|
|
39
|
+
### 原语(50)
|
|
40
|
+
|
|
41
|
+
| 类 | 文件 | 声明摘要 | 断点变体 | 状态修饰 |
|
|
42
|
+
| --- | --- | --- | --- | --- |
|
|
43
|
+
| `wf-absolute` | _position.css | position · position:absolute | — | — |
|
|
44
|
+
| `wf-app-shell` | _app-shell.css | display · grid-template-columns · height · overflow · display:grid · overflow:visible | — | — |
|
|
45
|
+
| `wf-block` | _block.css | display · display:block | — | — |
|
|
46
|
+
| `wf-center` | _center.css | align-items · display · flex-direction · justify-content · display:flex · flex-direction:column · align-items:… | — | — |
|
|
47
|
+
| `wf-cluster` | _cluster.css | align-items · display · flex-wrap · gap · justify-content · display:flex · flex-wrap:wrap · justify-content:va… | — | — |
|
|
48
|
+
| `wf-container` | _container.css | margin · max-width · padding · width | — | — |
|
|
49
|
+
| `wf-cover` | _cover.css | align-items · display · inset · justify-content · position · z-index · position:fixed · display:flex · align-i… | — | — |
|
|
50
|
+
| `wf-dim` | _hidden.css | opacity | — | — |
|
|
51
|
+
| `wf-fill` | _fill.css | flex · min-height · min-width · flex:1 | — | — |
|
|
52
|
+
| `wf-fill-hover` | _fill.css | background · border-radius · margin · padding · transition | — | — |
|
|
53
|
+
| `wf-flex` | _flex.css | display · display:flex | @@lg @@sm | — |
|
|
54
|
+
| `wf-grid` | _grid.css | display · gap · grid-template-columns · display:grid | — | — |
|
|
55
|
+
| `wf-hidden` | _hidden.css | display · display:none | @@lg | — |
|
|
56
|
+
| `wf-items-center` | _row.css | | — | — |
|
|
57
|
+
| `wf-items-end` | _row.css | | — | — |
|
|
58
|
+
| `wf-items-start` | _row.css | | — | — |
|
|
59
|
+
| `wf-items-stretch` | _row.css | | — | — |
|
|
60
|
+
| `wf-justify-between` | _justify.css | align-items · display · gap · justify-content · display:flex · justify-content:space-between · align-items:var… | — | — |
|
|
61
|
+
| `wf-justify-center` | _justify.css | align-items · display · gap · justify-content · display:flex · justify-content:center · align-items:var(--wf-a… | — | — |
|
|
62
|
+
| `wf-justify-end` | _justify.css | align-items · display · gap · justify-content · display:flex · justify-content:flex-end · align-items:var(--wf… | — | — |
|
|
63
|
+
| `wf-layer` | _layer.css | position · z-index · position:relative | — | — |
|
|
64
|
+
| `wf-main` | _app-shell.css | background · margin-inline · max-width · min-height · min-width · overflow · overflow-y · padding · overflow:v… | — | — |
|
|
65
|
+
| `wf-min-width-0` | _shrink.css | min-width | — | — |
|
|
66
|
+
| `wf-nav` | _app-shell.css | display · flex-direction · gap · display:flex · flex-direction:column | — | `wf-nav--collapsed` |
|
|
67
|
+
| `wf-nav--collapsed` | _app-shell.css | (基类 `wf-nav` 的状态修饰) | | |
|
|
68
|
+
| `wf-nav-group` | _app-shell.css | color · font-size · font-weight · letter-spacing · padding · text-transform | — | — |
|
|
69
|
+
| `wf-nav-item` | _app-shell.css | align-items · background · border · border-radius · box-shadow · color · cursor · display · font-family · font… | — | `wf-nav-item--active` |
|
|
70
|
+
| `wf-nav-item--active` | _app-shell.css | (基类 `wf-nav-item` 的状态修饰) | | |
|
|
71
|
+
| `wf-nowrap` | _nowrap.css | display · flex-wrap · gap · display:flex · flex-wrap:nowrap | — | — |
|
|
72
|
+
| `wf-overflow-auto` | _overflow.css | overflow · overflow:auto | — | — |
|
|
73
|
+
| `wf-overflow-hidden` | _overflow.css | overflow · overflow:hidden | — | — |
|
|
74
|
+
| `wf-overflow-x` | _overflow.css | overflow-x | — | — |
|
|
75
|
+
| `wf-pointer` | _hidden.css | cursor | — | — |
|
|
76
|
+
| `wf-relative` | _position.css | position · position:relative | — | — |
|
|
77
|
+
| `wf-row` | _row.css | align-items · display · flex-wrap · gap · display:flex · flex-wrap:wrap · align-items:var(--wf-align, center) | — | — |
|
|
78
|
+
| `wf-row-reverse` | _row.css | align-items · display · flex-direction · flex-wrap · gap · display:flex · flex-direction:row-reverse · flex-wr… | — | — |
|
|
79
|
+
| `wf-safe-bottom` | _safe-area.css | padding-bottom | — | — |
|
|
80
|
+
| `wf-safe-top` | _safe-area.css | padding-top | — | — |
|
|
81
|
+
| `wf-self-center` | _align-self.css | align-self | — | — |
|
|
82
|
+
| `wf-self-end` | _align-self.css | align-self | — | — |
|
|
83
|
+
| `wf-self-start` | _align-self.css | align-self | — | — |
|
|
84
|
+
| `wf-self-stretch` | _align-self.css | align-self | — | — |
|
|
85
|
+
| `wf-shrink` | _shrink.css | min-height · min-width | — | — |
|
|
86
|
+
| `wf-sidebar` | _app-shell.css | background · border-bottom · border-right · display · flex-direction · height · overflow-y · position · top · … | — | — |
|
|
87
|
+
| `wf-sidebar-body` | _app-shell.css | flex · overflow-y · padding · flex:1 | — | — |
|
|
88
|
+
| `wf-sidebar-footer` | _app-shell.css | border-top · flex-shrink · padding | — | — |
|
|
89
|
+
| `wf-sidebar-header` | _app-shell.css | align-items · border-bottom · display · flex-shrink · gap · padding · display:flex · align-items:center | — | — |
|
|
90
|
+
| `wf-split` | _split.css | align-items · display · flex-shrink · gap · justify-content · display:flex · justify-content:space-between · a… | — | — |
|
|
91
|
+
| `wf-stack` | _stack.css | align-items · display · flex-direction · gap · display:flex · flex-direction:column · align-items:var(--wf-ali… | — | — |
|
|
92
|
+
| `wf-sticky` | _sticky.css | position · top · position:sticky | — | — |
|
|
93
|
+
|
|
94
|
+
### 工具(98)
|
|
95
|
+
|
|
96
|
+
| 类 | 文件 | 声明摘要 | 断点变体 | 状态修饰 |
|
|
97
|
+
| --- | --- | --- | --- | --- |
|
|
98
|
+
| `wf-bg-error` | _surface.css | background | — | — |
|
|
99
|
+
| `wf-bg-none` | _surface.css | background | — | — |
|
|
100
|
+
| `wf-bg-primary` | _surface.css | background | — | — |
|
|
101
|
+
| `wf-bg-secondary` | _surface.css | background | — | — |
|
|
102
|
+
| `wf-bg-tertiary` | _surface.css | background | — | — |
|
|
103
|
+
| `wf-bg-warning` | _surface.css | background | — | — |
|
|
104
|
+
| `wf-bold` | _text.css | font-weight | — | — |
|
|
105
|
+
| `wf-border` | _border.css | border | — | — |
|
|
106
|
+
| `wf-border-bottom` | _border.css | border-bottom | — | — |
|
|
107
|
+
| `wf-border-left` | _border.css | border-left | — | — |
|
|
108
|
+
| `wf-border-none` | _border.css | border | — | — |
|
|
109
|
+
| `wf-border-right` | _border.css | border-right | — | — |
|
|
110
|
+
| `wf-border-top` | _border.css | border-top | — | — |
|
|
111
|
+
| `wf-break-word` | _text.css | overflow-wrap · word-break | — | — |
|
|
112
|
+
| `wf-bubble` | _surface.css | background · border-radius · color · display · font-size · line-height · max-width · padding · white-space · w… | — | `wf-bubble--ai` `wf-bubble--own` |
|
|
113
|
+
| `wf-bubble--ai` | _surface.css | (基类 `wf-bubble` 的状态修饰) | | |
|
|
114
|
+
| `wf-bubble--own` | _surface.css | (基类 `wf-bubble` 的状态修饰) | | |
|
|
115
|
+
| `wf-card-outline` | _surface.css | border | — | — |
|
|
116
|
+
| `wf-elevate` | _surface.css | box-shadow · outline · transform · transition | — | — |
|
|
117
|
+
| `wf-font-2xl` | _text.css | font-size | — | — |
|
|
118
|
+
| `wf-font-3xl` | _text.css | font-size | — | — |
|
|
119
|
+
| `wf-font-4xl` | _text.css | font-size | — | — |
|
|
120
|
+
| `wf-font-base` | _text.css | font-size | — | — |
|
|
121
|
+
| `wf-font-lg` | _text.css | font-size | — | — |
|
|
122
|
+
| `wf-font-mono` | _text.css | font-family | — | — |
|
|
123
|
+
| `wf-font-sm` | _text.css | font-size | — | — |
|
|
124
|
+
| `wf-font-xs` | _text.css | font-size | — | — |
|
|
125
|
+
| `wf-gap-lg` | _spacing.css | gap | — | — |
|
|
126
|
+
| `wf-gap-md` | _spacing.css | gap | — | — |
|
|
127
|
+
| `wf-gap-none` | _spacing.css | gap | — | — |
|
|
128
|
+
| `wf-gap-sm` | _spacing.css | gap | — | — |
|
|
129
|
+
| `wf-gap-xl` | _spacing.css | gap | — | — |
|
|
130
|
+
| `wf-gap-xs` | _spacing.css | gap | — | — |
|
|
131
|
+
| `wf-height-full` | _spacing.css | height | — | — |
|
|
132
|
+
| `wf-margin-bottom-lg` | _spacing.css | margin-bottom | — | — |
|
|
133
|
+
| `wf-margin-bottom-md` | _spacing.css | margin-bottom | — | — |
|
|
134
|
+
| `wf-margin-bottom-sm` | _spacing.css | margin-bottom | — | — |
|
|
135
|
+
| `wf-margin-bottom-xs` | _spacing.css | margin-bottom | — | — |
|
|
136
|
+
| `wf-margin-left-sm` | _spacing.css | margin-left | — | — |
|
|
137
|
+
| `wf-margin-left-xs` | _spacing.css | margin-left | — | — |
|
|
138
|
+
| `wf-margin-none` | _spacing.css | margin | — | — |
|
|
139
|
+
| `wf-margin-top-md` | _spacing.css | margin-top | — | — |
|
|
140
|
+
| `wf-margin-top-none` | _spacing.css | margin-top | — | — |
|
|
141
|
+
| `wf-margin-top-sm` | _spacing.css | margin-top | — | — |
|
|
142
|
+
| `wf-margin-top-xs` | _spacing.css | margin-top | — | — |
|
|
143
|
+
| `wf-margin-x-auto` | _spacing.css | margin-left · margin-right | — | — |
|
|
144
|
+
| `wf-margin-y-xs` | _spacing.css | margin-bottom · margin-top | — | — |
|
|
145
|
+
| `wf-medium` | _text.css | font-weight | — | — |
|
|
146
|
+
| `wf-nums` | _text.css | font-variant-numeric | — | — |
|
|
147
|
+
| `wf-padding-bottom-md` | _spacing.css | padding-bottom | — | — |
|
|
148
|
+
| `wf-padding-bottom-sm` | _spacing.css | padding-bottom | — | — |
|
|
149
|
+
| `wf-padding-bottom-xs` | _spacing.css | padding-bottom | — | — |
|
|
150
|
+
| `wf-padding-left-sm` | _spacing.css | padding-left | — | — |
|
|
151
|
+
| `wf-padding-lg` | _spacing.css | padding | — | — |
|
|
152
|
+
| `wf-padding-md` | _spacing.css | padding | — | — |
|
|
153
|
+
| `wf-padding-none` | _spacing.css | padding | — | — |
|
|
154
|
+
| `wf-padding-sm` | _spacing.css | padding | — | — |
|
|
155
|
+
| `wf-padding-top-sm` | _spacing.css | padding-top | — | — |
|
|
156
|
+
| `wf-padding-x-md` | _spacing.css | padding-left · padding-right | — | — |
|
|
157
|
+
| `wf-padding-x-sm` | _spacing.css | padding-left · padding-right | — | — |
|
|
158
|
+
| `wf-padding-x-xs` | _spacing.css | padding-left · padding-right | — | — |
|
|
159
|
+
| `wf-padding-xl` | _spacing.css | padding | — | — |
|
|
160
|
+
| `wf-padding-xs` | _spacing.css | padding | — | — |
|
|
161
|
+
| `wf-padding-y-lg` | _spacing.css | padding-bottom · padding-top | — | — |
|
|
162
|
+
| `wf-padding-y-md` | _spacing.css | padding-bottom · padding-top | — | — |
|
|
163
|
+
| `wf-padding-y-sm` | _spacing.css | padding-bottom · padding-top | — | — |
|
|
164
|
+
| `wf-padding-y-xs` | _spacing.css | padding-bottom · padding-top | — | — |
|
|
165
|
+
| `wf-panel-in` | _surface.css | animation · transform-origin | — | — |
|
|
166
|
+
| `wf-pill` | _surface.css | border-radius | — | — |
|
|
167
|
+
| `wf-pre-wrap` | _text.css | white-space · word-break | — | — |
|
|
168
|
+
| `wf-radius` | _surface.css | border-radius | — | — |
|
|
169
|
+
| `wf-radius-lg` | _surface.css | border-radius | — | — |
|
|
170
|
+
| `wf-radius-md` | _surface.css | border-radius | — | — |
|
|
171
|
+
| `wf-radius-sm` | _surface.css | border-radius | — | — |
|
|
172
|
+
| `wf-rounded-md` | _surface.css | border-radius | — | — |
|
|
173
|
+
| `wf-rounded-sm` | _surface.css | border-radius | — | — |
|
|
174
|
+
| `wf-semibold` | _text.css | font-weight | — | — |
|
|
175
|
+
| `wf-shadow` | _surface.css | box-shadow | — | — |
|
|
176
|
+
| `wf-surface` | _surface.css | background · border-radius · box-shadow | — | `wf-surface--flat` |
|
|
177
|
+
| `wf-surface--flat` | _surface.css | (基类 `wf-surface` 的状态修饰) | | |
|
|
178
|
+
| `wf-text-center` | _text.css | text-align | — | — |
|
|
179
|
+
| `wf-text-danger` | _text.css | color | — | — |
|
|
180
|
+
| `wf-text-error` | _text.css | color | — | — |
|
|
181
|
+
| `wf-text-left` | _text.css | text-align | — | — |
|
|
182
|
+
| `wf-text-nowrap` | _text.css | white-space | — | — |
|
|
183
|
+
| `wf-text-on-brand` | _text.css | color | — | — |
|
|
184
|
+
| `wf-text-on-warning` | _text.css | color | — | — |
|
|
185
|
+
| `wf-text-primary` | _text.css | color | — | — |
|
|
186
|
+
| `wf-text-right` | _text.css | text-align | — | — |
|
|
187
|
+
| `wf-text-secondary` | _text.css | color | — | — |
|
|
188
|
+
| `wf-text-success` | _text.css | color | — | — |
|
|
189
|
+
| `wf-text-tertiary` | _text.css | color | — | — |
|
|
190
|
+
| `wf-text-warning` | _text.css | color | — | — |
|
|
191
|
+
| `wf-tracking-wide` | _text.css | letter-spacing | — | — |
|
|
192
|
+
| `wf-truncate` | _text.css | overflow · text-overflow · white-space · overflow:hidden | — | — |
|
|
193
|
+
| `wf-uppercase` | _text.css | text-transform | — | — |
|
|
194
|
+
| `wf-width-full` | _spacing.css | width | — | — |
|
|
195
|
+
| `wf-width-sm` | _spacing.css | width | — | — |
|
|
196
|
+
|
|
197
|
+
### 内部(2)
|
|
198
|
+
|
|
199
|
+
| 类 | 文件 | 声明摘要 | 断点变体 | 状态修饰 |
|
|
200
|
+
| --- | --- | --- | --- | --- |
|
|
201
|
+
| `wf-popup` | _popup.css | box-sizing · max-width | — | — |
|
|
202
|
+
| `wf-popup-mask` | _popup.css | background · inset · position · z-index · position:fixed | — | — |
|
|
203
|
+
|
|
204
|
+
## 5. 间距标尺(双标尺定案——L13:gap 派生自 space 紧一档)
|
|
205
|
+
|
|
206
|
+
| 档 | space(内/外边距) | gap(容器内间距——派生) | 关系 |
|
|
207
|
+
| --- | --- | --- | --- |
|
|
208
|
+
| — | `--wf-space` = `12px` | `--wf-gap-md = var(--wf-space)` | 裸档即 md 档源 |
|
|
209
|
+
| xs | `4px` | `var(--wf-space-xs)` | gap 比 space 紧一档 |
|
|
210
|
+
| sm | `8px` | `var(--wf-space-sm)` | gap 比 space 紧一档 |
|
|
211
|
+
| md | `16px` | `var(--wf-space(裸))` | gap 比 space 紧一档 |
|
|
212
|
+
| lg | `24px` | `var(--wf-space-md)` | gap 比 space 紧一档 |
|
|
213
|
+
| xl | `32px` | `var(--wf-space-lg)` | gap 比 space 紧一档 |
|
|
214
|
+
| 2xl | `40px` | `var(--wf-space-xl)` | gap 比 space 紧一档 |
|
|
215
|
+
|
|
216
|
+
> 关系入代码:预设(compact)只覆写 space 标尺——gap 自动跟随;值冻结由 L13 守卫。
|
|
217
|
+
|
|
218
|
+
## 6. 零消费公共面(文档化定案——「示例 = 可发现」,不做裁剪)
|
|
219
|
+
|
|
220
|
+
以下类在代码语料(apps + src/client/components)零引用——属 weifuwu/layout npm 公共清单,
|
|
221
|
+
退出消费或库侧裁剪时才移除(登记单源:`layout-inventory.mjs` QUARTET_KEEP / LIB_SURFACE_KEEP);
|
|
222
|
+
现文档化(示例 = 可发现):
|
|
223
|
+
|
|
224
|
+
- `wf-absolute`:定位:`<div class="wf-absolute wf-inset-0">`(绝对定位铺满——需 position 上下文)
|
|
225
|
+
- `wf-cover`:媒体覆盖:`<div class="wf-cover"><img /></div>`(绝对定位全铺容器)
|
|
226
|
+
- `wf-layer`:层叠原语:`<div class="wf-layer wf-z-pop">`(相对定位层,按 z 叠放)
|
|
227
|
+
- `wf-nav`:导航条:`<nav class="wf-nav"><a class="wf-nav-item">…`(横向导航——内部项自带命中区)
|
|
228
|
+
- `wf-nav-group`:导航分组:`<div class="wf-nav-group">`(导航项分组容器/标签)
|
|
229
|
+
- `wf-radius-lg`:圆角档:`class="wf-radius-lg"`(大圆角——不在半径标尺逐档之外的独立值)
|
|
230
|
+
- `wf-safe-bottom`:底部安全区:`class="wf-safe-bottom"`(env(safe-area-inset-bottom)——iOS 底部)
|
|
231
|
+
- `wf-safe-top`:顶部安全区:`class="wf-safe-top"`(env(safe-area-inset-top)——刘海屏)
|
|
232
|
+
- `wf-self-start`:cross-axis 单项定位:`class="wf-self-start"`(align-self: flex-start——与 wf-self-stretch 同族)
|
|
233
|
+
|
|
234
|
+
> showcase 演示页私有类(`wf-variant-toggle/chevron/name/desc`——页面上下文定义,非库面)不计入。
|
|
235
|
+
|
|
236
|
+
## 7. 计数速览(L1/L6 哨兵口径)
|
|
237
|
+
|
|
238
|
+
| 面 | 数量 |
|
|
239
|
+
| --- | --- |
|
|
240
|
+
| 布局原语 | 50 |
|
|
241
|
+
| 工具类 | 98 |
|
|
242
|
+
| 内部类 | 2 |
|
|
243
|
+
| 主题 token | 178 |
|