weifuwu 0.79.0 → 0.80.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.
Files changed (47) hide show
  1. package/README.md +7 -6
  2. package/dist/ai/client.d.ts +1 -1
  3. package/dist/ai/sse.d.ts +1 -1
  4. package/dist/ai/types.d.ts +2 -2
  5. package/dist/components/ChatInput/ChatInput.d.ts +10 -0
  6. package/dist/components/Input/Input.d.ts +2 -0
  7. package/dist/components/index.js +10 -10
  8. package/dist/index.js +156 -157
  9. package/dist/ui-dom/ai.d.ts +1 -1
  10. package/dist/ui-dom/context.d.ts +32 -0
  11. package/dist/ui-dom/index.d.ts +9 -9
  12. package/dist/ui-dom/index.js +10 -10
  13. package/dist/ui-dom/jsx-runtime.js +1 -1
  14. package/dist/ui-dom/{vdom → middleware}/serve.d.ts +5 -8
  15. package/dist/ui-dom/testing.js +1 -1
  16. package/dist/ui-dom/use-chat.d.ts +1 -1
  17. package/dist/ui-dom/{vdom → vdom2}/audit.d.ts +5 -5
  18. package/dist/ui-dom/{vdom → vdom2}/build.d.ts +5 -5
  19. package/dist/ui-dom/vdom2/ctx.d.ts +32 -0
  20. package/dist/ui-dom/vdom2/hydrate.d.ts +13 -0
  21. package/dist/ui-dom/vdom2/index.d.ts +13 -0
  22. package/dist/ui-dom/vdom2/kind.d.ts +35 -0
  23. package/dist/ui-dom/vdom2/mount.d.ts +63 -0
  24. package/dist/ui-dom/vdom2/patch.d.ts +47 -0
  25. package/dist/ui-dom/vdom2/render.d.ts +19 -0
  26. package/dist/ui-dom/vdom2/ssr.d.ts +32 -0
  27. package/dist/ui-dom/vdom2/trace.d.ts +52 -0
  28. package/dist/ui-dom/{vdom → vdom2}/transform.d.ts +9 -3
  29. package/dist/ui-dom/vdom2/transitions.d.ts +23 -0
  30. package/dist/ui-dom/vdom2/x2html.d.ts +23 -0
  31. package/dist/ui-dom/vnode.d.ts +63 -70
  32. package/docs/ai-contract.md +418 -0
  33. package/docs/components-map.md +4 -4
  34. package/docs/frontend-ui-dom.md +2 -2
  35. package/docs/frontend.md +2 -2
  36. package/docs/layout.md +1 -1
  37. package/docs/mobile.md +1 -1
  38. package/docs/saas.md +2 -2
  39. package/docs/style-guide.md +182 -0
  40. package/package.json +1 -1
  41. package/dist/ui-dom/vdom/diff.d.ts +0 -29
  42. package/dist/ui-dom/vdom/hydration.d.ts +0 -17
  43. package/dist/ui-dom/vdom/index.d.ts +0 -23
  44. package/dist/ui-dom/vdom/mount.d.ts +0 -58
  45. package/dist/ui-dom/vdom/render.d.ts +0 -17
  46. package/dist/ui-dom/vdom/ssr.d.ts +0 -44
  47. /package/dist/ui-dom/{vdom → vdom2}/registry.d.ts +0 -0
package/docs/frontend.md CHANGED
@@ -233,7 +233,7 @@ const Counter: Component = async (_init, ctx) => {
233
233
  }
234
234
  ```
235
235
 
236
- **render-only 唯一规则**:渲染只发生在 `render()` 调用处(design/render-only-plan.md)——
236
+ **render-only 唯一规则**:渲染只发生在 `render()` 调用处——
237
237
  状态是普通对象(`let` / `createStore`),**没有 `$` Proxy、没有赋值自动渲染**。改状态后必须显式 `ctx.ui.render()`。
238
238
 
239
239
  ### `createStore` + `ctx.ui.useExternal()` — 跨组件共享状态
@@ -448,7 +448,7 @@ ctx.ui.render(['stats'])
448
448
 
449
449
  #### `ctx.ui.useChat(options)` — AI 对话会话(AiChat 配套)
450
450
 
451
- 会话语义的流式 AI 状态容器:消息累积 / 工具调用内嵌 / HITL 审批 / stop / retry,协议对页面完全透明(wf: 协议见 `design/ai-contract.md`)。返回 handle 带 `subscribe(cb)`——子组件用 `ctx.ui.useExternal(chat)` 订阅会话变化(render-only 共享状态原语):
451
+ 会话语义的流式 AI 状态容器:消息累积 / 工具调用内嵌 / HITL 审批 / stop / retry,协议对页面完全透明(wf: 协议见 `docs/ai-contract.md`)。返回 handle 带 `subscribe(cb)`——子组件用 `ctx.ui.useExternal(chat)` 订阅会话变化(render-only 共享状态原语):
452
452
 
453
453
  ```tsx
454
454
  // mount 阶段(服务端 `ai()` 中间件 + `AiChat` 组件配套)
package/docs/layout.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  纯 CSS 58 个布局原语 + 136 个工具类 + 167 个主题 Token。不绑定任何 JS 框架。
6
6
 
7
- > **学习路径与命名规范**:见 [`design/style-guide.md`](../design/style-guide.md)——统一语法 `wf-<域>-<名>`、三档学习(组件 → 10 核心原语 → 完整速查)、场景速查、变量定制。
7
+ > **学习路径与命名规范**:见 [`docs/style-guide.md`](style-guide.md)——统一语法 `wf-<域>-<名>`、三档学习(组件 → 10 核心原语 → 完整速查)、场景速查、变量定制。
8
8
 
9
9
  > **全栈 weifuwu 项目**:`weifuwu/components/style.css` 已包含布局系统,一条 import 就够了,无需单独引用本页。
10
10
  > 本页仅适用于**非 weifuwu 项目**或**只需 CSS 布局**的场景。
package/docs/mobile.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # 移动端开发指南(weifuwu)
2
2
 
3
3
  > 移动端友好由框架构造保证:**用对原语 + 守 audit 规则**,不靠每个组件"记得"。
4
- > 落地依据:`design/mobile-support-plan.md`(P0/P1 已完成,P2 进行中)。
4
+ > 落地依据:移动端支持计划(P0-P3 全落地——usePopup 全系 + safe-area + 44px 命中区 + docs/mobile 指南)。
5
5
 
6
6
  ## 一、断点体系(布局原语)
7
7
 
package/docs/saas.md CHANGED
@@ -147,7 +147,7 @@ import { ai } from 'weifuwu'
147
147
  const a = ai() // DEEPSEEK_API_KEY / BASE_URL / MODEL 自动读 env,默认 deepseek-v4-flash
148
148
  app.use(a) // 注入 ctx.ai(worker/非请求场景也可直接 a.chat())
149
149
 
150
- // 流式对话:路由一行返回 SSE(wf: 协议,详见 design/ai-contract.md)
150
+ // 流式对话:路由一行返回 SSE(wf: 协议,详见 docs/ai-contract.md)
151
151
  app.post('/api/chat', async (req, ctx) => {
152
152
  const { messages } = await req.json()
153
153
  return ctx.ai.stream({ messages }, {
@@ -217,7 +217,7 @@ return () => <AiChat chat={$} />
217
217
 
218
218
  > 分层:`ctx.ai`(后端协议)→ `aiStream`(传输解码)→ `useChat`(会话语义)→ `AiChat`(标准界面)。要完全自定义 UI 的应用用 useChat + 自有渲染;要 5 分钟出界面用 AiChat。
219
219
 
220
- - **协议**:`wf:` 命名空间(message_start/token/tool_call/tool_progress/usage/done/error + agent 扩展 step/approval_request),SSE 下行 + POST 上行,错误即值、未知事件透传、`x:*` 自定义事件(详见 [design/ai-contract.md](../design/ai-contract.md))
220
+ - **协议**:`wf:` 命名空间(message_start/token/tool_call/tool_progress/usage/done/error + agent 扩展 step/approval_request),SSE 下行 + POST 上行,错误即值、未知事件透传、`x:*` 自定义事件(详见 [docs/ai-contract.md](ai-contract.md))
221
221
  - **agent 引擎**:`a.agent({ systemPrompt, tools, humanInTheLoop })` 工具循环(LLM → tool_call → 执行 → 回喂 → 重复);工具可 `emit` 进度/自定义事件、接收 `signal` 取消;HITL 审批(`ctx.ai.approve` 响应,拒绝≠终止、modified 改参、超时兜底)
222
222
  - **emitter 抽象**:`agent.stream(messages, { emit })`——`wf:*` 事件(step/token/tool_result/usage/done)可接任意通道(SSE/WS/回调),协议不焊死在传输层;`agent.runToResult(messages)` 返回结构化结果 `{ content, steps, usage }`(非流式/worker 场景)
223
223
  - **embedding**:`ctx.ai.embed(text)` / `embedMany(texts)` 向量化(默认 `DASHSCOPE_API_KEY` + `text-embedding-v4`,compatible-mode 端点);未配置抛 `AiError('unsupported')`(惰性检查,不静默降级)——知识库/语义检索开箱即用
@@ -0,0 +1,182 @@
1
+ # weifuwu/style 使用指南(wf-* 命名规范 + 三档学习路径)
2
+
3
+ > 一个 CSS 文件(`weifuwu/components/style.css`)= Token + 布局原语 + 工具类 + 组件样式。
4
+ > 本文档是**学习路径**与**命名规范**——看完第二档即可上手 90% 页面。
5
+
6
+ ## 统一语法:`wf-<域>-<名字>`
7
+
8
+ 所有类遵循一个规则:`wf-` + **域** + 名字。
9
+
10
+ | 域 | 例子 | 说明 |
11
+ |---|---|---|
12
+ | `layout`(布局原语) | `wf-layout-stack` `wf-layout-split` `wf-layout-grid` | 元素之间的空间关系 |
13
+ | `p/m/gap/w/h`(间距尺寸) | `wf-p-md` `wf-mt-lg` `wf-gap-sm` `wf-w-full` | padding/margin/gap/width/height |
14
+ | `border/rounded`(边框圆角) | `wf-border-b` `wf-rounded-md` `wf-pill` | |
15
+ | `bg/text/weight/leading/align/tracking`(视觉) | `wf-bg-primary` `wf-text-secondary` `wf-weight-semibold` `wf-leading-base` | |
16
+ | `btn/card/modal/…`(组件域) | `wf-btn--primary` `wf-card--hover` | 组件由 props 渲染,一般不需手写 |
17
+
18
+ **修饰符号**:
19
+ ```
20
+ wf-card--active -- = 变体/状态(选中/激活/hover)
21
+ wf-modal-header - = 子元素(组件内部结构,不手写)
22
+ wf-layout-stack@md @ = 断点变体(≥768px 时横向)
23
+ ```
24
+
25
+ **值类(裸词)**:单值工具没有属性域——`wf-uppercase` `wf-truncate` `wf-pre-wrap` `wf-dim` `wf-pill`。
26
+
27
+ ## 三档学习路径
28
+
29
+ ### 第一档:只用组件(0 成本)
30
+
31
+ 48 个组件覆盖页面功能块,完全不需要 wf-*:
32
+
33
+ ```tsx
34
+ <PageHeader title="订单"><Button variant="primary">+ 新建</Button></PageHeader>
35
+ <Table data={orders} columns={cols} />
36
+ <Card hover><StatCard value="1,234" label="总用户" /></Card>
37
+ ```
38
+
39
+ ### 第二档:10 个核心原语(半小时,覆盖 90% 页面)
40
+
41
+ ```
42
+ wf-layout-stack 垂直堆叠 + gap
43
+ wf-layout-row 水平排列 + wrap
44
+ wf-layout-split 两端分布
45
+ wf-layout-fill flex: 1 撑满
46
+ wf-gap-md 设置间距(配合上面)
47
+ wf-p-md 内边距
48
+ wf-text-secondary 次级文字
49
+ wf-bg-primary 品牌浅底
50
+ wf-border-b 下边框
51
+ wf-rounded-md 圆角
52
+ ```
53
+
54
+ ```tsx
55
+ <div class="wf-layout-split">
56
+ <div class="wf-layout-row wf-gap-md">
57
+ <Card>…</Card>
58
+ </div>
59
+ <Button variant="primary">提交</Button>
60
+ </div>
61
+ ```
62
+
63
+ ### 第三档:完整速查(按需查 IDE 补全)
64
+
65
+ 输入 `wf-layout-` / `wf-text-` / `wf-bg-` 弹出全部候选。完整清单见 README「布局系统」。
66
+
67
+ ## 场景速查("我要做什么")
68
+
69
+ | 需求 | 写法 |
70
+ |---|---|
71
+ | 两个元素两端分布 | `wf-layout-split` |
72
+ | 一列堆叠带间距 | `wf-layout-stack wf-gap-md` |
73
+ | 一行换行居中对齐 | `wf-layout-row wf-gap-md wf-layout-cluster` |
74
+ | 卡片网格 | `<div class="wf-layout-grid">` |
75
+ | 状态色文字/背景 | `wf-text-success` / `wf-bg-error` |
76
+ | 卡片 hover 抬升 | `<Card hover>` 或 `wf-elevate` |
77
+ | 聊天气泡 | `wf-bubble` / `wf-bubble--own` |
78
+ | 文章正文排版 | `<article class="wf-prose">` |
79
+ | 隐藏元素(桌面显示/移动隐藏) | `wf-layout-hidden@sm` |
80
+ | 按钮变胶囊 | `:root { --wf-btn-radius: 999px }` |
81
+ | 数字防抖(统计/表格数值) | `wf-nums`(StatCard 已默认套用) |
82
+ | 顶级页面大标题 | `<PageHeader display>` 或 `wf-text-display` |
83
+ | 状态/计数徽章 | `<Badge variant>`(不可交互,含 dot) |
84
+ | 可关闭标签 | `<Tag closable>`(可交互,有关闭钮) |
85
+ | 图标 | `<Icon name="close" />`(禁止裸 emoji/字形) |
86
+
87
+ ## 定制(零 CSS 文件)
88
+
89
+ ### 品牌换色 — 改原始层一个值,全站跟随
90
+
91
+ ```html
92
+ <style>
93
+ :root { --wf-brand-500: #7c3aed; } /* 亮色品牌 */
94
+ :root { --wf-dark-brand-500: #a78bfa; } /* 暗色品牌(可选) */
95
+ </style>
96
+ ```
97
+
98
+ ### 组件定制 — 设一个变量
99
+
100
+ ```html
101
+ <style>
102
+ :root {
103
+ --wf-modal-width: 640px;
104
+ --wf-btn-radius: 999px;
105
+ --wf-field-height: 44px;
106
+ --wf-card-shadow: 0 8px 24px rgba(0,0,0,.12);
107
+ }
108
+ </style>
109
+ ```
110
+
111
+ 完整钩子清单:`--wf-btn-*` `--wf-card-*` `--wf-field-*` `--wf-modal-*` `--wf-drawer-width` `--wf-toast-*` `--wf-alert-radius` `--wf-badge-radius` `--wf-tag-radius` `--wf-switch-radius` `--wf-popover-*` `--wf-tooltip-radius` `--wf-dropdown-min-width` `--wf-datepicker-*`。
112
+
113
+ ### 动效定制 — 时长/缓动/位移
114
+
115
+ ```html
116
+ <style>
117
+ :root {
118
+ --wf-dur-base: 300ms; /* 默认动画时长 */
119
+ --wf-ease-out: cubic-bezier(0.22, 1, 0.36, 1); /* 入场缓动 */
120
+ --wf-motion-lg: 32px; /* 抽屉全幅位移 */
121
+ }
122
+ </style>
123
+ ```
124
+
125
+ ### 覆盖优先级(@layer)
126
+
127
+ ```
128
+ @layer tokens, base, layout, utilities, components; ← weifuwu 的层
129
+ 未分层的用户 CSS 天然最高优先级 ← 你写的普通规则直接生效
130
+ 用户 @layer utilities 可精准盖过 weifuwu 的 utilities
131
+ ```
132
+
133
+ ## 主题 Token(141 个,双层)
134
+
135
+ - **原始层**(`--wf-brand-*` `--wf-slate-*` `--wf-dark-*`):色值只定义一次,品牌/暗色调校改这里
136
+ - **语义层**(`--wf-color-*` `--wf-space-*` `--wf-radius-*` …):组件消费,主题切换覆盖这里
137
+ - 暗色模式:`--wf-dark-*` 间接层映射,两段激活(`data-theme` / 系统偏好),无硬编码
138
+
139
+ ### 动效 Token(P8 新增,全站动效统一引用)
140
+
141
+ | Token | 默认 | 用途 |
142
+ |---|---|---|
143
+ | `--wf-dur-fast/base/slow` | 120/200/300ms | 动画时长阶梯 |
144
+ | `--wf-ease-out` | `cubic-bezier(0.16,1,0.3,1)` | 入场(快出缓停) |
145
+ | `--wf-ease-in` | `cubic-bezier(0.4,0,1,1)` | 退场(渐入加速) |
146
+ | `--wf-ease-snap` | `cubic-bezier(0.34,1.56,0.64,1)` | 选中/弹跳(Segmented 等) |
147
+ | `--wf-motion-sm/md/lg` | 4/8/24px | 位移量(toast 退场/抽屉) |
148
+
149
+ ### 语义文字色(P2 新增,浅底可读)
150
+
151
+ `--wf-color-{primary,success,warning,error,info}-text`(700 级,对 50 级底对比度 ≥ 4.5:1)——**文字用 `-text` 变体,500 级只做填充/边框/焦点**。实心填充上的文字用 `--wf-color-on-brand`;遮罩用 `--wf-overlay`。
152
+
153
+ ### CJK / 数字(P5 新增)
154
+
155
+ - `--wf-heading-case: none`(默认)——表头/分组标题文本变换,英文项目可覆盖 `uppercase`
156
+ - `--wf-nums`——`wf-nums` 工具类的取值(tabular-nums,数字防宽度抖动)
157
+
158
+ ## 图标(Icon 组件)
159
+
160
+ 组件库内置 `Icon`(stroke SVG、`currentColor`、`1em` 随字号、`aria-hidden`),组件内部图标统一用它——**禁止裸文本字形**(✕✓⚠▲▼ 等):
161
+
162
+ ```tsx
163
+ h(Icon, { name: 'close' }) // 随上下文颜色/字号
164
+ h(Icon, { name: 'check', size: 16 })
165
+ ```
166
+
167
+ 内置 25 个:方向(chevron/arrow/sort)、状态(check/close/alert/info/warning)、操作(search/send/stop/retry/upload/trash/edit/plus)等。业务图标自备(`Icon` 只做基础集)。
168
+
169
+ ## 浮层退场语义(P0/P4 变更,注意时序)
170
+
171
+ Modal/Drawer/Confirm/Toast 关闭时**先播退场动画再卸载**:
172
+
173
+ - `open=false` 后 DOM 仍存在约 200ms(播 `--exit` 动画)——时序敏感代码(测量/立即重开)需知悉
174
+ - `prefers-reduced-motion: reduce` 下动画降为 0.01ms,等效立即卸载
175
+ - Confirm 默认 `maskClosable=false`(遮罩点击不取消,防误触);Escape 仍可关闭
176
+
177
+ ## 边界(诚实说明)
178
+
179
+ - 业务具体尺寸(`width: 220px`、`min-height: 120px`)用内联——设计系统不背业务值
180
+ - 深度定制组件结构用覆盖 CSS(@layer 友好支持)
181
+ - 低频 CSS(float/filter)不做类——用内联或组件
182
+ - 动效已统一由 Token 驱动:新增动画禁止硬编码时长/缓动(audit 把关)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "weifuwu",
3
3
  "type": "module",
4
- "version": "0.79.0",
4
+ "version": "0.80.0",
5
5
  "description": "AI SaaS framework — (req, ctx) => Response",
6
6
  "exports": {
7
7
  ".": {
@@ -1,29 +0,0 @@
1
- /**
2
- * vdom/diff — 同步 patch(阶段 2)
3
- *
4
- * **不变量:diff 只处理已构建树**——组件 vnode 必已 `_render`/`_child`(buildVNode 预构建)。
5
- * 遇未构建组件 → throw(开发期暴露;生产路径 renderByIds/导航都先 buildVNode await)。
6
- * 这是第 1 代死循环的根治:diff 永不调用组件工厂、无 resolve 回调、无补全循环。
7
- *
8
- * 三态 skip:props 同 + 无 dirty + ctx 版本同 → 复用旧 _child(renderFn 不重跑)。
9
- */
10
- import type { VNodeChild } from '../vnode.ts';
11
- import { arrayChildren } from '../vnode.ts';
12
- export { arrayChildren };
13
- export interface PatchCtx {
14
- browser: any;
15
- registry: import('./registry.ts').Registry;
16
- /** 当前 ctx 版本号(三态 skip 版本比较:组件 _ctxVersion !== 当前版本 → 不 skip,
17
- * 强制重渲染——bumpCtxVersion 递增后所有组件重跑 renderFn,如 i18n 切换语言) */
18
- ctxVersion?: number;
19
- /** force:跳过三态 skip(mountRoot.rerender 全量重跑用) */
20
- force?: boolean;
21
- }
22
- /**
23
- * patchValue — 同步 diff 单一节点。
24
- * @returns newInput 的实际 DOM(null = 无 DOM)
25
- */
26
- export declare function patchValue(parent: Node, oldNode: Node | null, oldInput: VNodeChild, newInput: VNodeChild, ctx: PatchCtx): Node | null;
27
- /** 属性 patch(只设不删语义保持简单;差异删除由 diff 上层处理) */
28
- export declare function patchProps(el: Element, oldProps: Record<string, any>, newProps: Record<string, any>): void;
29
- export declare function patchChildren(parent: Node, oldInput: VNodeChild | null | undefined, newInput: VNodeChild | null | undefined, ctx: PatchCtx, oldRange?: Node[], oldAnchors?: (Node | null)[], anchorOut?: (Node | null)[]): (Node | null)[];
@@ -1,17 +0,0 @@
1
- /**
2
- * vdom/hydration — 游标收养(SSR HTML → 客户端,不重建 DOM)
3
- *
4
- * 与第 1 代 hydration 的区别:**先 buildVNode 预构建**(await 工厂——组件已 resolve、
5
- * _child 已展开)→ 再游标收养(只接线属性/事件/ref——不重跑 renderFn/工厂)。
6
- *
7
- * 游标不变量:元素/文本 VNode 恰好消耗一个游标节点;组件/Fragment/数组透明;
8
- * null 消耗零;创建时 insertBefore(游标) 且游标不动;收养/替换时游标前进。
9
- */
10
- import type { VNode } from '../vnode.ts';
11
- import type { WfuiContext } from '../types.ts';
12
- import { mountAsyncComponent } from './build.ts';
13
- /** Hydration 入口:buildVNode 预构建(await 工厂)→ 游标收养 */
14
- export declare function hydrateVNode(container: Element, vnode: VNode, ctx: WfuiContext): Promise<void>;
15
- /** 给组件 vnode 分配 id(hydration 需要——注册表定位) */
16
- export declare function ensureHydrationId(vnode: VNode, ctx: WfuiContext): void;
17
- export { mountAsyncComponent };
@@ -1,23 +0,0 @@
1
- /**
2
- * vdom — 全新虚拟 DOM 引擎(第 2 代)
3
- *
4
- * 设计初衷(修复第 1 代死循环/动态挂载问题):
5
- * - 组件 vnode 进入 diff 前**必须已构建**(`_render` 已设)——diff 永不调用组件工厂
6
- * - 构建(buildVNode)是 async 的,统一在渲染入口完成(首帧 / renderByIds / 导航)
7
- * - 动态挂载组件在 buildVNode 阶段被 await(构建完成)→ diff 同步渲染——
8
- * 无占位、无注释、无「resolve 回调触发补全」(第 1 代死循环根因)
9
- * - 工厂只跑一次(vnode 级缓存 + 旧树同位置同类型复用)——无无限挂载
10
- *
11
- * 两阶段异步组件(唯一签名):
12
- * async (initProps, ctx) => Promise<(props) => VNode | null>
13
- */
14
- export { buildVNode } from './build.ts';
15
- export { renderValue } from './render.ts';
16
- export { patchValue } from './diff.ts';
17
- export { createRenderer, type Renderer } from './mount.ts';
18
- export { createRegistry, type Registry } from './registry.ts';
19
- export { createStore, type ExternalStore } from '../store.ts';
20
- export { mountRoot, createVdomContext, mountCommand, unmountCommand, createCommandContainer } from './mount.ts';
21
- export { hydrateVNode } from './hydration.ts';
22
- export { renderSsr, ssrPage, ssrToString, serializeData, createSsrContext } from './ssr.ts';
23
- export { uiServe, type UIServeOptions, type UIServeHandle } from './serve.ts';
@@ -1,58 +0,0 @@
1
- /**
2
- * vdom/mount — 挂载入口(首帧 + ctx/ui 组装)
3
- *
4
- * 渲染管线:buildVNode(async 预构建)→ renderValue(同步落地)。
5
- * ctx.ui:render/setMounting/endMounting——render-only(design/render-only-plan.md)。
6
- */
7
- import type { VNode, VNodeChild, Component } from '../vnode.ts';
8
- import type { WfuiContext } from '../types.ts';
9
- import type { BrowserEnv } from '../types.ts';
10
- import { type Registry } from './registry.ts';
11
- export interface MountOptions {
12
- browser: BrowserEnv;
13
- root: HTMLElement;
14
- registry?: Registry;
15
- renderer?: Renderer;
16
- onError?: (e: unknown) => void;
17
- }
18
- export interface MountHandle {
19
- ctx: WfuiContext;
20
- registry: Registry;
21
- renderer: Renderer;
22
- /** 挂载根组件 */
23
- mount(comp: Component | VNodeChild): Promise<void>;
24
- /** 整树强制重渲染(force——测试辅助/手动刷新:renderFn 重跑 + patch) */
25
- rerender(): Promise<void>;
26
- /** 卸载(清理 DOM) */
27
- unmount(): void;
28
- }
29
- export interface VdomContext {
30
- ctx: WfuiContext;
31
- registry: Registry;
32
- renderer: Renderer;
33
- rootUi: any;
34
- destroyPopupListeners: () => void;
35
- }
36
- export interface Renderer {
37
- render(ids?: string[]): Promise<void>;
38
- }
39
- export interface RendererOptions {
40
- registry: Registry;
41
- ctx: WfuiContext;
42
- rootEl?: HTMLElement;
43
- onError?: (e: unknown) => void;
44
- }
45
- export declare function createRenderer(opts: RendererOptions): Renderer;
46
- /** 组装 vdom 渲染上下文(ctx/registry/renderer/rootUi——含完整 hooks 转发) */
47
- export declare function createVdomContext(opts: MountOptions): VdomContext;
48
- export declare function mountRoot(opts: MountOptions): MountHandle;
49
- /** vdom 命令式挂载:buildVNode(await 工厂)→ renderValue → append + _parentNode */
50
- export declare function mountCommand(container: HTMLElement, vnode: VNode, ctx: WfuiContext, opts?: {
51
- onMounted?: () => void;
52
- }): {
53
- id: string;
54
- };
55
- /** vdom 命令式卸载:ref 清理 + 卸载钩子 + 容器移除 */
56
- export declare function unmountCommand(container: HTMLElement, vnode: VNode | null, ctx: WfuiContext): void;
57
- /** 创建命令式挂载容器(body 下独立 div) */
58
- export declare function createCommandContainer(): HTMLDivElement | null;
@@ -1,17 +0,0 @@
1
- /**
2
- * vdom/render — DOM 落地(阶段 2 同步)
3
- *
4
- * **只处理已构建的组件**(`_render` 已设——buildVNode 已 await 工厂)。
5
- * 遇未构建组件 → 抛错(开发期暴露 bug;生产路径 renderByIds 先 build 后 patch,
6
- * 不会出现未构建组件)。
7
- */
8
- import type { VNodeChild } from '../vnode.ts';
9
- import type { BrowserEnv } from '../types.ts';
10
- export { EVENT_RE, eventTarget, ENUMERATED_VALUE_BASED, holeDetail, holeMarkup } from './transform.ts';
11
- export declare const SVG_TAGS: Set<string>;
12
- export declare function setProp(el: Element, key: string, value: any): void;
13
- /** 占位内容(规则表 §1——wf-hole 内容可见可审计:false/null/undefined/true/对象摘要/bad-vnode) */
14
- /** 创建占位节点(数组上下文的无渲染值 → 注释节点,childNodes 与数组同构——规则表 §1) */
15
- export declare function createHole(browser: BrowserEnv, v: unknown): Node | null;
16
- /** 递归渲染(同步——组件必须已构建) */
17
- export declare function renderValue(v: VNodeChild, ctx: any, browser?: BrowserEnv, key?: string | null, id?: string | null, fid?: string | null): Node | null;
@@ -1,44 +0,0 @@
1
- /**
2
- * vdom/ssr — 服务端渲染(无 DOM,纯字符串)
3
- *
4
- * SSR 与引擎无关(vnode → HTML 字符串)——vdom 独立实现:
5
- * - renderSsr:await 工厂 → renderFn → 递归(组件签名两阶段 async)
6
- * - createSsrContext:SSR ctx shim(hooks no-op、$ 普通对象、ctx.data 预取)
7
- * - ssrPage:router.execute → renderSsr → 完整 HTML(__DATA__ 种子)
8
- *
9
- * 渲染期非确定性(Date/Math.random/locale)导致 SSR/hydration mismatch——
10
- * dev 检测,文档红线(AGENTS.md §3.5 诚实裁剪)。
11
- */
12
- import type { VNodeChild, Component } from '../vnode.ts';
13
- import type { WfuiContext } from '../types.ts';
14
- import type { UIRouter } from '../router.ts';
15
- /** HTML 转义(文本/属性值) */
16
- export declare function escape(s: string): string;
17
- /** 渲染 vnode → HTML 字符串(服务端) */
18
- export declare function renderSsr(input: VNodeChild, ctx: WfuiContext): Promise<string>;
19
- /** 创建 SSR ctx(serverCtx 注入 + dataStore 预取 + hooks shim) */
20
- export declare function createSsrContext(serverCtx: any, dataStore: Map<string, unknown>): WfuiContext;
21
- /** 序列化数据存储 → window.__DATA__ 脚本(防 XSS:转义 <) */
22
- export declare function serializeData(data: Map<string, unknown>): string;
23
- export interface SsrPageResult {
24
- html: string;
25
- /** __DATA__ 脚本(hydration 种子) */
26
- dataScript: string;
27
- /** 完整 HTML(含 dataScript) */
28
- page: string;
29
- }
30
- /**
31
- * SSR 渲染路由页面 → 完整 HTML(Node 无 DOM)。
32
- * 客户端 uiServe(router, { root, hydrate: true }) 收养。
33
- */
34
- export declare function ssrPage(router: UIRouter, opts: {
35
- url: string;
36
- title?: string;
37
- lang?: string;
38
- rootId?: string;
39
- styles?: string[];
40
- }): Promise<SsrPageResult>;
41
- /** SSR 渲染组件 → HTML 片段 */
42
- export declare function ssrToString(Comp: Component, props: Record<string, any>, serverCtx: any, opts?: {
43
- data?: Map<string, unknown>;
44
- }): Promise<string>;
File without changes