weifuwu 0.71.0 → 0.72.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 (164) hide show
  1. package/README.md +58 -47
  2. package/dist/components/Accordion/Accordion.d.ts +1 -1
  3. package/dist/components/Affix/Affix.d.ts +1 -1
  4. package/dist/components/AiChat/AiChat.d.ts +2 -2
  5. package/dist/components/Alert/Alert.d.ts +1 -1
  6. package/dist/components/AlertGroup/AlertGroup.d.ts +1 -1
  7. package/dist/components/Anchor/Anchor.d.ts +1 -1
  8. package/dist/components/ApprovalCard/ApprovalCard.d.ts +1 -1
  9. package/dist/components/AspectRatio/AspectRatio.d.ts +1 -1
  10. package/dist/components/AutoComplete/AutoComplete.d.ts +1 -1
  11. package/dist/components/Avatar/Avatar.d.ts +1 -1
  12. package/dist/components/AvatarGroup/AvatarGroup.d.ts +1 -1
  13. package/dist/components/BackTop/BackTop.d.ts +1 -1
  14. package/dist/components/Badge/Badge.d.ts +1 -1
  15. package/dist/components/Breadcrumb/Breadcrumb.d.ts +1 -1
  16. package/dist/components/Button/Button.d.ts +1 -1
  17. package/dist/components/Calendar/Calendar.d.ts +1 -1
  18. package/dist/components/Card/Card.d.ts +1 -1
  19. package/dist/components/Carousel/Carousel.d.ts +1 -1
  20. package/dist/components/Cascader/Cascader.d.ts +1 -1
  21. package/dist/components/Chart/Chart.d.ts +1 -1
  22. package/dist/components/Checkbox/Checkbox.d.ts +1 -1
  23. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +1 -1
  24. package/dist/components/CodeBlock/CodeBlock.d.ts +1 -1
  25. package/dist/components/Collapse/Collapse.d.ts +1 -1
  26. package/dist/components/ColorPicker/ColorPicker.d.ts +1 -1
  27. package/dist/components/Command/Command.d.ts +1 -1
  28. package/dist/components/Confirm/Confirm.d.ts +2 -2
  29. package/dist/components/ContextMenu/ContextMenu.d.ts +1 -1
  30. package/dist/components/CopyButton/CopyButton.d.ts +1 -1
  31. package/dist/components/DatePicker/DatePicker.d.ts +1 -1
  32. package/dist/components/Descriptions/Descriptions.d.ts +1 -1
  33. package/dist/components/DiffView/DiffView.d.ts +1 -1
  34. package/dist/components/Divider/Divider.d.ts +1 -1
  35. package/dist/components/Drawer/Drawer.d.ts +1 -1
  36. package/dist/components/Dropdown/Dropdown.d.ts +1 -1
  37. package/dist/components/Editor/Editor.d.ts +1 -1
  38. package/dist/components/Editor/tools/toolbar.d.ts +1 -1
  39. package/dist/components/EmptyState/EmptyState.d.ts +1 -1
  40. package/dist/components/Field/Field.d.ts +1 -1
  41. package/dist/components/FileUpload/FileUpload.d.ts +1 -1
  42. package/dist/components/FloatButton/FloatButton.d.ts +1 -1
  43. package/dist/components/Form/Form.d.ts +1 -1
  44. package/dist/components/Grid/Grid.d.ts +1 -1
  45. package/dist/components/Highlight/Highlight.d.ts +1 -1
  46. package/dist/components/HoverCard/HoverCard.d.ts +2 -2
  47. package/dist/components/Icon/Icon.d.ts +1 -1
  48. package/dist/components/Img/Img.d.ts +1 -1
  49. package/dist/components/InView/InView.d.ts +1 -1
  50. package/dist/components/InfiniteScroll/InfiniteScroll.d.ts +1 -1
  51. package/dist/components/Input/Input.d.ts +1 -1
  52. package/dist/components/InputNumber/InputNumber.d.ts +1 -1
  53. package/dist/components/JSONViewer/JSONViewer.d.ts +1 -1
  54. package/dist/components/Kanban/Kanban.d.ts +1 -1
  55. package/dist/components/Label/Label.d.ts +1 -1
  56. package/dist/components/Layout/Layout.d.ts +1 -1
  57. package/dist/components/Link/Link.d.ts +1 -1
  58. package/dist/components/List/List.d.ts +1 -1
  59. package/dist/components/Loading/Loading.d.ts +1 -1
  60. package/dist/components/LogViewer/LogViewer.d.ts +1 -1
  61. package/dist/components/Markdown/Markdown.d.ts +1 -1
  62. package/dist/components/Mentions/Mentions.d.ts +1 -1
  63. package/dist/components/Menu/Menu.d.ts +1 -1
  64. package/dist/components/Menubar/Menubar.d.ts +1 -1
  65. package/dist/components/MessageBubble/MessageBubble.d.ts +1 -1
  66. package/dist/components/Modal/Modal.d.ts +1 -1
  67. package/dist/components/NavMenu/NavMenu.d.ts +1 -1
  68. package/dist/components/Notification/Notification.d.ts +2 -2
  69. package/dist/components/PageHeader/PageHeader.d.ts +1 -1
  70. package/dist/components/Pagination/Pagination.d.ts +1 -1
  71. package/dist/components/PasswordInput/PasswordInput.d.ts +1 -1
  72. package/dist/components/PinInput/PinInput.d.ts +1 -1
  73. package/dist/components/Pipeline/Pipeline.d.ts +1 -1
  74. package/dist/components/Popconfirm/Popconfirm.d.ts +2 -2
  75. package/dist/components/Popover/Popover.d.ts +2 -2
  76. package/dist/components/ProgressBar/ProgressBar.d.ts +1 -1
  77. package/dist/components/QRCode/QRCode.d.ts +1 -1
  78. package/dist/components/RadioGroup/RadioGroup.d.ts +1 -1
  79. package/dist/components/Rate/Rate.d.ts +1 -1
  80. package/dist/components/Resizable/Resizable.d.ts +1 -1
  81. package/dist/components/Result/Result.d.ts +1 -1
  82. package/dist/components/Scrollbar/Scrollbar.d.ts +1 -1
  83. package/dist/components/SearchInput/SearchInput.d.ts +1 -1
  84. package/dist/components/SegmentedControl/SegmentedControl.d.ts +1 -1
  85. package/dist/components/Select/Select.d.ts +1 -1
  86. package/dist/components/Skeleton/Skeleton.d.ts +1 -1
  87. package/dist/components/Slider/Slider.d.ts +1 -1
  88. package/dist/components/Space/Space.d.ts +1 -1
  89. package/dist/components/Sparkline/Sparkline.d.ts +1 -1
  90. package/dist/components/StatCard/StatCard.d.ts +1 -1
  91. package/dist/components/Steps/Steps.d.ts +1 -1
  92. package/dist/components/Switch/Switch.d.ts +1 -1
  93. package/dist/components/Table/Table.d.ts +1 -1
  94. package/dist/components/Tabs/Tabs.d.ts +1 -1
  95. package/dist/components/Tag/Tag.d.ts +1 -1
  96. package/dist/components/TagsInput/TagsInput.d.ts +1 -1
  97. package/dist/components/Textarea/Textarea.d.ts +1 -1
  98. package/dist/components/ThemeSwitch/ThemeSwitch.d.ts +1 -1
  99. package/dist/components/Timeline/Timeline.d.ts +1 -1
  100. package/dist/components/Toast/Toast.d.ts +2 -2
  101. package/dist/components/ToggleGroup/ToggleGroup.d.ts +1 -1
  102. package/dist/components/ToolCallCard/ToolCallCard.d.ts +1 -1
  103. package/dist/components/Tooltip/Tooltip.d.ts +2 -2
  104. package/dist/components/Tour/Tour.d.ts +1 -1
  105. package/dist/components/Transfer/Transfer.d.ts +1 -1
  106. package/dist/components/Tree/Tree.d.ts +1 -1
  107. package/dist/components/TreeSelect/TreeSelect.d.ts +1 -1
  108. package/dist/components/Typography/Typography.d.ts +1 -1
  109. package/dist/components/VirtualList/VirtualList.d.ts +1 -1
  110. package/dist/components/VirtualTable/VirtualTable.d.ts +1 -1
  111. package/dist/components/Watermark/Watermark.d.ts +1 -1
  112. package/dist/components/index.js +12 -12
  113. package/dist/dev/index.js +1 -1
  114. package/dist/index.js +4 -4
  115. package/dist/ui/index.d.ts +1 -1
  116. package/dist/ui/ssr-page.d.ts +1 -1
  117. package/dist/ui/ssr.d.ts +1 -1
  118. package/dist/ui-dom/Confirm.d.ts +44 -0
  119. package/dist/ui-dom/Notification.d.ts +70 -0
  120. package/dist/ui-dom/Toast.d.ts +43 -0
  121. package/dist/ui-dom/index.d.ts +33 -0
  122. package/dist/ui-dom/index.js +18 -0
  123. package/dist/ui-dom/jsx-runtime.d.ts +4 -0
  124. package/dist/ui-dom/jsx-runtime.js +1 -0
  125. package/dist/ui-dom/popup-tracker.d.ts +36 -0
  126. package/dist/ui-dom/registry.d.ts +39 -0
  127. package/dist/{client → ui-dom}/render.d.ts +2 -1
  128. package/dist/ui-dom/router.d.ts +66 -0
  129. package/dist/ui-dom/serve.d.ts +28 -0
  130. package/dist/ui-dom/ssr.d.ts +56 -0
  131. package/dist/{client → ui-dom}/types.d.ts +22 -0
  132. package/dist/{client → ui-dom}/ui.d.ts +2 -0
  133. package/dist/{client → ui-dom}/vnode.d.ts +13 -12
  134. package/docs/custom-components.md +2 -0
  135. package/docs/frontend-middleware.md +3 -1
  136. package/docs/frontend-ui-dom.md +110 -0
  137. package/docs/frontend.md +3 -1
  138. package/docs/realtime.md +2 -0
  139. package/docs/saas.md +2 -0
  140. package/package.json +7 -7
  141. package/dist/client/app.d.ts +0 -26
  142. package/dist/client/error-boundary.d.ts +0 -23
  143. package/dist/client/index.d.ts +0 -54
  144. package/dist/client/index.js +0 -6
  145. package/dist/client/registry.d.ts +0 -49
  146. package/dist/client/router.d.ts +0 -27
  147. package/dist/client/type-flow.test.d.ts +0 -7
  148. /package/dist/{client → ui-dom}/ai.d.ts +0 -0
  149. /package/dist/{client → ui-dom}/browser.d.ts +0 -0
  150. /package/dist/{client → ui-dom}/diff.d.ts +0 -0
  151. /package/dist/{client → ui-dom}/focus-trap.d.ts +0 -0
  152. /package/dist/{client → ui-dom}/hydration.d.ts +0 -0
  153. /package/dist/{client → ui-dom}/i18n.d.ts +0 -0
  154. /package/dist/{client → ui-dom}/locale/en_US.d.ts +0 -0
  155. /package/dist/{client → ui-dom}/locale/zh_CN.d.ts +0 -0
  156. /package/dist/{client → ui-dom}/middleware/api.d.ts +0 -0
  157. /package/dist/{client → ui-dom}/middleware/auth.d.ts +0 -0
  158. /package/dist/{client → ui-dom}/middleware/ws.d.ts +0 -0
  159. /package/dist/{client → ui-dom}/motion.d.ts +0 -0
  160. /package/dist/{client → ui-dom}/popup.d.ts +0 -0
  161. /package/dist/{client → ui-dom}/reactive.d.ts +0 -0
  162. /package/dist/{client → ui-dom}/route-match.d.ts +0 -0
  163. /package/dist/{client → ui-dom}/scroll-lock.d.ts +0 -0
  164. /package/dist/{client → ui-dom}/use-chat.d.ts +0 -0
package/README.md CHANGED
@@ -23,7 +23,7 @@ npm install weifuwu # 一个依赖,完整应用栈
23
23
  | 层 | 入口 | 能力 |
24
24
  |----|------|------|
25
25
  | 后端 | `weifuwu` | Trie 路由 / 中间件链 / serve / 自研 PG+Redis / SSR / GraphQL / WebSocket |
26
- | 前端 | `weifuwu/client` | 两阶段组件 / Proxy 渲染 / 数据管道 / 路由 / api·auth·ws·i18n / 移动端原语 / **ctx.browser 环境抽象**(组件零 window/document) |
26
+ | 前端 | `weifuwu/ui-dom` | **UIRouter(纯路由 + ctx 注入链)+ uiServe(渲染运行时)+ SSR/hydration**——handler=异步组件 / 中间件两阶段 / ctx.params 对齐后端;**weifuwu/components 直接复用**(VNode 契约唯一来源 ui-dom,见 `docs/frontend-ui-dom.md`) |
27
27
  | 组件 | `weifuwu/components` | 109 个 HTML 原语组件(表单/表格/弹层/AiChat…),引用 `--wf-*` 主题变量 |
28
28
  | 样式 | `weifuwu/layout` | 57 布局原语 + 136 工具类 + 167 主题 Token,零自定义 CSS 文件 |
29
29
  | SaaS 地基 | 随包内置 | rateLimit / email / userSystem / messager / queue / ai → `ctx.*` 一行接入 |
@@ -125,9 +125,10 @@ npm install weifuwu # 一个依赖,完整应用栈
125
125
  ### 先写共享部分(两种模式都一样)
126
126
 
127
127
  ```tsx
128
- // routes.tsx —— 页面声明(前后端共用)
129
- import type { RouteDef } from 'weifuwu/client'
130
- import { asyncComponent } from 'weifuwu/client'
128
+ // routes.tsx —— 页面声明(前后端共用 UIRouter)
129
+ import { UIRouter, asyncComponent } from 'weifuwu/ui-dom'
130
+
131
+ const app = new UIRouter()
131
132
 
132
133
  // async 工厂组件:await 数据 → 返回视图(两阶段:外层初始化,内层渲染)
133
134
  const Home = asyncComponent(async (ctx) => {
@@ -136,7 +137,9 @@ const Home = asyncComponent(async (ctx) => {
136
137
  (props) => <h1>{msg.msg}</h1>
137
138
  })
138
139
 
139
- export const routes: RouteDef[] = [{ path: '/', component: Home }]
140
+ app.get('/', async () => <Home />) // handler = 异步组件
141
+
142
+ export { app }
140
143
  ```
141
144
 
142
145
  ### 模式 A:纯 SPA
@@ -144,30 +147,31 @@ export const routes: RouteDef[] = [{ path: '/', component: Home }]
144
147
  ```ts
145
148
  // server.ts
146
149
  import { serve, Router, ui, cors } from 'weifuwu'
150
+ import { app } from './routes.tsx'
147
151
 
148
- const app = new Router()
149
- app.use(cors())
150
- app.use(ui()) // 注入 ctx.ui.html / ctx.ui.js / ctx.ui.css
152
+ const router = new Router()
153
+ router.use(cors())
154
+ router.use(ui()) // 注入 ctx.ui.html / ctx.ui.js / ctx.ui.css
151
155
 
152
156
  // SPA 外壳(空 root + 前端 bundle)
153
- app.get('/', (req, ctx) => ctx.ui.html`
157
+ router.get('/', (req, ctx) => ctx.ui.html`
154
158
  <!doctype html><html><body>
155
159
  <div id="root"></div>
156
160
  <script src="/static/app.js"></script>
157
161
  </body></html>
158
162
  `)
159
- app.get('/static/app.js', (req, ctx) => ctx.ui.js('./src/client.ts'))
160
- app.get('/api/hello', () => Response.json({ msg: 'world' }))
163
+ router.get('/static/app.js', (req, ctx) => ctx.ui.js('./src/client.ts'))
164
+ router.get('/api/hello', () => Response.json({ msg: 'world' }))
161
165
 
162
- serve(app, { port: 3000 })
166
+ serve(router, { port: 3000 })
163
167
  ```
164
168
 
165
169
  ```ts
166
170
  // src/client.ts —— 纯客户端渲染
167
- import { createApp, router, RouteView } from 'weifuwu/client'
168
- import { routes } from './routes.tsx'
171
+ import { uiServe } from 'weifuwu/ui-dom'
172
+ import { app } from './routes.tsx'
169
173
 
170
- createApp().use(router({ routes })).mount('#root', RouteView)
174
+ uiServe(app, { root: '#root' }) // 监听 location → 执行路由 → VDOM 落地
171
175
  ```
172
176
 
173
177
  ### 模式 B:SSR + Hydration(内容页/SEO)
@@ -175,31 +179,35 @@ createApp().use(router({ routes })).mount('#root', RouteView)
175
179
  同一份 `routes`、同一个组件,差异只在**后端加 `uiSsr` 一行、客户端加 `hydrate` 参数**:
176
180
 
177
181
  ```ts
178
- // server.ts —— 完整版(与模式 A 的差异:uiSsr 中间件 + 一条样式路由)
179
- import { serve, Router, ui, uiSsr, cors } from 'weifuwu'
180
- import { routes } from './routes.tsx'
182
+ // server.ts —— 完整版(与模式 A 的差异:ssrPage + 一条样式路由)
183
+ import { serve, Router, ui, cors } from 'weifuwu'
184
+ import { ssrPage } from 'weifuwu/ui-dom'
185
+ import { app } from './routes.tsx'
181
186
 
182
- const app = new Router()
183
- app.use(cors())
184
- app.use(ui())
187
+ const router = new Router()
188
+ router.use(cors())
189
+ router.use(ui())
185
190
 
186
- // 路由级 SSR:GET 匹配 routes → 注入 ctx.route.params → await 组件工厂
191
+ // 路由级 SSR:GET 匹配共享 router → 注入 ctx.params → await 组件工厂
187
192
  // → 完整 HTML + __DATA__ + bundle/styles 引用(无需手写页面 handler)
188
- app.use(uiSsr({ routes, bundle: '/static/app.js', styles: ['/static/style.css'] }))
193
+ router.get('*', async (req, ctx) => {
194
+ const { page } = await ssrPage(app, { url: req.url ?? '/' })
195
+ return ctx.ui.html(page)
196
+ })
189
197
 
190
- app.get('/static/app.js', (req, ctx) => ctx.ui.js('./src/client.ts'))
191
- app.get('/static/style.css', (req, ctx) => ctx.ui.css('./src/style.css'))
192
- app.get('/api/hello', () => Response.json({ msg: 'world' }))
198
+ router.get('/static/app.js', (req, ctx) => ctx.ui.js('./src/client.ts'))
199
+ router.get('/static/style.css', (req, ctx) => ctx.ui.css('./src/style.css'))
200
+ router.get('/api/hello', () => Response.json({ msg: 'world' }))
193
201
 
194
- serve(app, { port: 3000 })
202
+ serve(router, { port: 3000 })
195
203
  ```
196
204
 
197
205
  ```ts
198
206
  // src/client.ts —— 与模式 A 的唯一差异:hydrate: true(收养服务端 HTML,无闪跳)
199
- import { createApp, router, RouteView } from 'weifuwu/client'
200
- import { routes } from './routes.tsx'
207
+ import { uiServe } from 'weifuwu/ui-dom'
208
+ import { app } from './routes.tsx'
201
209
 
202
- createApp().use(router({ routes })).mount('#root', RouteView, { hydrate: true })
210
+ uiServe(app, { root: '#root', hydrate: true })
203
211
  ```
204
212
 
205
213
  ### 启动(两种模式都一样)
@@ -245,7 +253,7 @@ cd apps/agent-platform && npm run seed && npm run dev
245
253
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
246
254
  <title>Weifuwu CDN 示例</title>
247
255
 
248
- <!-- 组件样式(可选,如只用 weifuwu/client 则不需要) -->
256
+ <!-- 组件样式(可选,如只用 weifuwu/ui-dom 则不需要) -->
249
257
  <link
250
258
  rel="stylesheet"
251
259
  href="https://unpkg.com/weifuwu@latest/dist/components/style.css"
@@ -258,14 +266,14 @@ cd apps/agent-platform && npm run seed && npm run dev
258
266
  <script type="importmap">
259
267
  {
260
268
  "imports": {
261
- "weifuwu/client": "https://unpkg.com/weifuwu@latest/dist/client/index.js",
269
+ "weifuwu/ui-dom": "https://unpkg.com/weifuwu@latest/dist/ui-dom/index.js",
262
270
  "weifuwu/components": "https://unpkg.com/weifuwu@latest/dist/components/index.js"
263
271
  }
264
272
  }
265
273
  </script>
266
274
 
267
275
  <script type="module">
268
- import { createApp, h } from 'weifuwu/client'
276
+ import { UIRouter, uiServe, h } from 'weifuwu/ui-dom'
269
277
  import { Card, Button, Badge } from 'weifuwu/components'
270
278
 
271
279
  // 组件 = (initProps, ctx) => (props) => VNode
@@ -291,7 +299,10 @@ cd apps/agent-platform && npm run seed && npm run dev
291
299
  )
292
300
  }
293
301
 
294
- createApp().mount('#root', Counter)
302
+ // 路由 + 渲染:监听 location → 执行 handler → VDOM 落地
303
+ const app = new UIRouter()
304
+ app.get('/', () => h(Counter, {}))
305
+ uiServe(app, { root: '#root' })
295
306
  </script>
296
307
  </body>
297
308
  </html>
@@ -303,7 +314,7 @@ cd apps/agent-platform && npm run seed && npm run dev
303
314
 
304
315
  | 资源 | CDN 地址 | 说明 |
305
316
  |------|---------|------|
306
- | `weifuwu/client` | `https://unpkg.com/weifuwu@latest/dist/client/index.js` | 客户端核心(createApp, h, 路由, 状态管理等) |
317
+ | `weifuwu/ui-dom` | `https://unpkg.com/weifuwu@latest/dist/ui-dom/index.js` | 前端运行时(UIRouter, uiServe, h, 状态管理等) |
307
318
  | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 102 个 UI 组件(Button, Card, Table, Modal, Icon 等) |
308
319
  | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 167 个主题 Token + 57 个布局原语 + 136 个工具类 |
309
320
  | 独立布局系统 | `https://unpkg.com/weifuwu@latest/dist/layout/weifuwu-layout.css` | 仅 CSS 布局,不依赖 JS |
@@ -336,17 +347,16 @@ cd apps/agent-platform && npm run seed && npm run dev
336
347
  | `weifuwu` | **ok / badRequest / …** | HTTP 响应辅助函数(ok/badRequest/... 等 12 个) | — |
337
348
  | `weifuwu` | **parseBody** | JSON 请求体安全解析 | — |
338
349
  | Router 方法 | **app.graphql()** | GraphQL 端点(支持 GraphiQL),Router 实例方法(无需单独 import) | Router |
339
- | `weifuwu/client` | **createApp** | 应用引导 + VDOM 渲染引擎 | — |
340
- | `weifuwu/client` | **router / RouteView** | 前端路由(history/hash 模式) | createApp |
341
- | `weifuwu/client` | **asyncComponent** | async 工厂组件:工厂层声明数据,mount/render 同步(三条纪律见[核心概念](#核心概念)) | — |
342
- | `weifuwu/client` | **ctx.data** | 数据管道:SSR 预取 / hydration 命中 / SPA fetch(`ctx.data.get`) | createApp |
343
- | `weifuwu/client` | **api / auth / ws** | HTTP 客户端 / 认证 / WebSocket 中间件 | createApp |
344
- | `weifuwu/client` | **i18n** | 国际化中间件(运行时切换语言) | createApp |
345
- | `weifuwu/client` | **ErrorBoundary** | 错误边界组件 | createApp |
346
- | `weifuwu/client` | **lockScroll/trapFocus** | 滚动锁定 / 焦点陷阱工具 | — |
347
- | `weifuwu/client` | **popup** | 弹层 fixed 定位工具(`computeFixedPos` / `computeFixedPosRect` / `clampToViewport`) | — |
348
- | `weifuwu/client` | **事件原语** | `usePopup` / `useDialog` / `usePresence` / `useInView` / `useScrollPosition` / `useGlobalKey` / `useDrag` / `useDragDrop` / `useAnimationEnd` / `useTween` / `useReducedMotion`(浏览器事件/动画统一入口,见 [docs/mobile.md](docs/mobile.md)) | — |
349
- | `weifuwu/components` | **113 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/client |
350
+ | `weifuwu/ui-dom` | **UIRouter** | 纯路由 + ctx 注入链(`use` 中间件累积类型,对齐后端 `app.use`);handler=异步组件 | — |
351
+ | `weifuwu/ui-dom` | **uiServe** | 渲染运行时:监听 location → 执行路由 → VDOM diff/patch;`hydrate: true` 收养 SSR HTML | UIRouter |
352
+ | `weifuwu/ui-dom` | **asyncComponent** | async 工厂组件:工厂层声明数据,mount/render 同步(三条纪律见[核心概念](#核心概念)) | — |
353
+ | `weifuwu/ui-dom` | **ctx.data** | 数据管道:SSR 预取 / hydration 命中 / SPA fetch(`ctx.data.get`) | uiServe |
354
+ | `weifuwu/ui-dom` | **api / auth / ws** | HTTP 客户端 / 认证 / WebSocket 中间件 | |
355
+ | `weifuwu/ui-dom` | **i18n** | 国际化中间件(运行时切换语言) | |
356
+ | `weifuwu/ui-dom` | **ssrPage / serializeData** | 服务端渲染:SSR HTML + `__DATA__` 序列化(`ctx.params` 两端同源) | |
357
+ | `weifuwu/ui-dom` | **useChat / AiChat 原语** | AI 会话(流式/工具调用/HITL) | — |
358
+ | `weifuwu/ui-dom` | **事件原语** | `usePopup` / `useDialog` / `usePresence` / `useInView` / `useScrollPosition` / `useGlobalKey` / `useDrag` / `useDragDrop` / `useAnimationEnd` / `useTween` / `useReducedMotion`(浏览器事件/动画统一入口,见 [docs/mobile.md](docs/mobile.md)) | — |
359
+ | `weifuwu/components` | **113 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/ui-dom |
350
360
  | `weifuwu/layout` | **CSS 布局** | 57 个布局原语 + 136 个工具类 + 167 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
351
361
 
352
362
  ---
@@ -358,7 +368,7 @@ cd apps/agent-platform && npm run seed && npm run dev
358
368
  | 任务 | 用 | 位置 |
359
369
  |------|-----|------|
360
370
  | 起 HTTP 服务 + 路由 | `serve(app)` + `new Router()` + `app.get/post/...` | [docs/server.md](docs/server.md) |
361
- | 渲染页面(SPA / SSR+hydrate) | `ui()` + `uiSsr({ routes })`;`createApp()` + `router({ routes })` + `RouteView` | [docs/realtime.md](docs/realtime.md) · [docs/frontend.md](docs/frontend.md) |
371
+ | 渲染页面(SPA / SSR+hydrate) | `ui()` + `ssrPage(router)`;`uiServe(router, { root, hydrate })` | [docs/frontend-ui-dom.md](docs/frontend-ui-dom.md) · [docs/frontend.md](docs/frontend.md) |
362
372
  | 数据持久化 | `postgres()` → `` ctx.sql`SELECT *` `` · `redis()` → `ctx.redis` | [docs/data.md](docs/data.md) |
363
373
  | 数据管道(SSR 预取/hydration/SPA) | `ctx.data.get(key)` + `asyncComponent` | [docs/frontend.md](docs/frontend.md) |
364
374
  | 用户注册/登录/会话/多租户 | `userSystem()` → `ctx.auth` + `/api/auth/*` | [docs/saas.md](docs/saas.md) |
@@ -489,6 +499,7 @@ README 只保留入门内容(设计理念 / 快速开始 / 核心概念 / 模
489
499
  | 文档 | 内容 |
490
500
  |------|------|
491
501
  | [docs/frontend.md](docs/frontend.md) | 前端核心:createApp / 组件模型 / 状态管理 / 条件与列表 / ref / 类型 |
502
+ | [docs/frontend-ui-dom.md](docs/frontend-ui-dom.md) | **ui-dom**:UIRouter 纯路由 + uiServe 渲染运行时 + ctx 注入链 + components 复用 + SSR/hydration(前端唯一运行时——weifuwu/client 已删除) |
492
503
  | [docs/frontend-middleware.md](docs/frontend-middleware.md) | 前端中间件:router / api / auth / ws / i18n / ErrorBoundary / confirm / toast / ScrollLock / extendCtx |
493
504
  | [docs/components.md](docs/components.md) | 组件库(113 个组件 + 使用示例 + 组件列表) |
494
505
  | [docs/layout.md](docs/layout.md) | 布局系统:57 个布局原语 + 136 个工具类 + 167 个主题 Token |
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface AccordionItem {
3
3
  key: string;
4
4
  title: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface AffixProps {
3
3
  /** 距视口顶部偏移,滚动超过该值后固定(px),默认 0 */
4
4
  offsetTop?: number;
@@ -18,8 +18,8 @@
18
18
  * return () => h(AiChat, { chat: $ })
19
19
  * ```
20
20
  */
21
- import type { Component } from '../../client/vnode.ts';
22
- import type { UseChatHandle, UiMessage } from '../../client/use-chat.ts';
21
+ import type { Component } from '../../ui-dom/vnode.ts';
22
+ import type { UseChatHandle, UiMessage } from '../../ui-dom/use-chat.ts';
23
23
  import type { WfError, WfUsage } from '../../ai/types.ts';
24
24
  export interface AiChatLabels {
25
25
  send: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export type AlertVariant = 'info' | 'success' | 'warning' | 'error';
3
3
  export interface AlertProps {
4
4
  variant?: AlertVariant;
@@ -9,7 +9,7 @@
9
9
  * 裁剪(CS-05):合并阈值固定 3 条起(少于此退化为平铺);
10
10
  * 不做时间线分组/虚拟化。
11
11
  */
12
- import type { Component } from '../../client/vnode.ts';
12
+ import type { Component } from '../../ui-dom/vnode.ts';
13
13
  export interface AlertGroupItem {
14
14
  id: string;
15
15
  message: any;
@@ -5,7 +5,7 @@
5
5
  * 滚动侦听:ctx.ui.useScrollPosition(全局/容器 scroll 监听 + rAF 节流,内置方案)。
6
6
  * 裁剪:嵌套滚动容器、滚动容器非视口(container 未提供时仅视口)、自动生成标题锚点。
7
7
  */
8
- import type { Component } from '../../client/vnode.ts';
8
+ import type { Component } from '../../ui-dom/vnode.ts';
9
9
  export interface AnchorItem {
10
10
  href: string;
11
11
  title: any;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  import type { WfApprovalRequest } from '../../ai/types.ts';
3
3
  /**
4
4
  * ApprovalCard — 人工审批卡片(wf: 协议 §4.5 交互原语)
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface AspectRatioProps {
3
3
  /** 宽/高比,默认 16/9 */
4
4
  ratio?: number;
@@ -13,7 +13,7 @@
13
13
  * 裁剪(CS-05):不做分组/虚拟化候选(Select searchable 覆盖分组场景);
14
14
  * 自定义渲染用 `renderOption` 透传。
15
15
  */
16
- import type { Component } from '../../client/vnode.ts';
16
+ import type { Component } from '../../ui-dom/vnode.ts';
17
17
  export interface AutoCompleteOption {
18
18
  value: string;
19
19
  label?: any;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface AvatarProps {
3
3
  name?: string;
4
4
  src?: string;
@@ -5,7 +5,7 @@
5
5
  * 用于群聊成员、协作人列表。
6
6
  * 裁剪:不做 hover 展开 tooltip(见 roadmap)。
7
7
  */
8
- import type { Component } from '../../client/vnode.ts';
8
+ import type { Component } from '../../ui-dom/vnode.ts';
9
9
  import { type AvatarProps } from '../Avatar/Avatar.ts';
10
10
  export interface AvatarGroupItem {
11
11
  name?: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface BackTopProps {
3
3
  /** 滚动超过此高度显示(px),默认 400 */
4
4
  visibilityHeight?: number;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'error';
3
3
  export interface BadgeProps {
4
4
  variant?: BadgeVariant;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface BreadcrumbItem {
3
3
  label: string;
4
4
  href?: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface ButtonProps {
3
3
  variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
4
4
  size?: 'sm' | 'md' | 'lg';
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CalendarEvent {
3
3
  key: string;
4
4
  /** 日期 'YYYY-MM-DD' */
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CardProps {
3
3
  variant?: 'default' | 'outlined';
4
4
  /** 便捷:outlined = variant 'outlined' */
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CarouselProps {
3
3
  children: any[];
4
4
  /** 自动播放 */
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CascaderOption {
3
3
  value: string;
4
4
  label: string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * weifuwu/components — Chart
3
3
  */
4
- import type { Component } from '../../client/vnode.ts';
4
+ import type { Component } from '../../ui-dom/vnode.ts';
5
5
  import type { DataPoint, ChartType, ChartOptions } from './chart-utils.ts';
6
6
  export type { DataPoint, ChartType, ChartOptions };
7
7
  export interface ChartProps {
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CheckboxProps {
3
3
  label?: string;
4
4
  checked?: boolean;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CheckboxGroupOption {
3
3
  value: string;
4
4
  label: string;
@@ -5,7 +5,7 @@
5
5
  * (highlight.ts tokenizer——零依赖 FS-05)。
6
6
  * 由 Markdown 代码围栏复用;也可独立使用。
7
7
  */
8
- import type { Component } from '../../client/vnode.ts';
8
+ import type { Component } from '../../ui-dom/vnode.ts';
9
9
  export interface CodeBlockProps {
10
10
  code: string;
11
11
  lang?: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CollapseItem {
3
3
  key: string;
4
4
  title: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface ColorPickerProps {
3
3
  /** 受控颜色值(hex,如 #4f6ef7) */
4
4
  value?: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CommandItem {
3
3
  key: string;
4
4
  label: string;
@@ -4,8 +4,8 @@
4
4
  * 声明式:基于 Modal 封装,footer 自带「取消 / 确定」按钮。
5
5
  * 命令式:confirm() 中间件注入 ctx.confirm(),返回 Promise<boolean>。
6
6
  */
7
- import type { Component } from '../../client/vnode.ts';
8
- import type { AppMiddleware } from '../../client/types.ts';
7
+ import type { Component } from '../../ui-dom/vnode.ts';
8
+ import type { AppMiddleware } from '../../ui-dom/types.ts';
9
9
  export interface ConfirmProps {
10
10
  open?: boolean;
11
11
  title?: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface ContextMenuItem {
3
3
  key: string;
4
4
  label: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface CopyButtonProps {
3
3
  /** 要复制的文本 */
4
4
  value: string;
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * 状态管理:闭包变量 + ctx.ui.render()
8
8
  */
9
- import type { Component } from '../../client/vnode.ts';
9
+ import type { Component } from '../../ui-dom/vnode.ts';
10
10
  export type DatePickerMode = 'date' | 'datetime' | 'time' | 'range';
11
11
  export interface DatePickerProps {
12
12
  mode?: DatePickerMode;
@@ -4,7 +4,7 @@
4
4
  * 详情字段展示:label/value 栅格(<dl> 语义结构,屏幕阅读器友好)。
5
5
  * 用于 Agent 配置展示、实体详情、订单信息等只读字段场景。
6
6
  */
7
- import type { Component } from '../../client/vnode.ts';
7
+ import type { Component } from '../../ui-dom/vnode.ts';
8
8
  export interface DescriptionItem {
9
9
  label: any;
10
10
  value: any;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface DiffViewProps {
3
3
  /** 旧代码 */
4
4
  oldCode: string;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface DividerProps {
3
3
  vertical?: boolean;
4
4
  children?: any;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * weifuwu/components — Drawer
3
3
  */
4
- import type { Component } from '../../client/vnode.ts';
4
+ import type { Component } from '../../ui-dom/vnode.ts';
5
5
  export type DrawerPosition = 'left' | 'right';
6
6
  export interface DrawerProps {
7
7
  open?: boolean;
@@ -4,7 +4,7 @@
4
4
  * usePopup 组合器:click 触发 + 受控 open + 外部点击/Escape(document 级,
5
5
  * 弹层在 portal 中按 Escape 也能关)+ 定位/视口 clamp + portal。
6
6
  */
7
- import type { Component } from '../../client/vnode.ts';
7
+ import type { Component } from '../../ui-dom/vnode.ts';
8
8
  export interface DropdownItem {
9
9
  label: string;
10
10
  value?: string;
@@ -7,7 +7,7 @@
7
7
  * 使用两阶段模型 + VDOM innerHTML 支持。
8
8
  * 状态管理:闭包变量 + ctx.ui.render()
9
9
  */
10
- import type { Component } from '../../client/vnode.ts';
10
+ import type { Component } from '../../ui-dom/vnode.ts';
11
11
  import type { EditorProps } from './tools/types.ts';
12
12
  export type { EditorProps, ToolbarItem } from './tools/types.ts';
13
13
  export declare const Editor: Component<EditorProps>;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * weifuwu/components/Editor/tools — 工具栏渲染
3
3
  */
4
- import type { VNode } from '../../../client/vnode.ts';
4
+ import type { VNode } from '../../../ui-dom/vnode.ts';
5
5
  import type { FormatState, ToolbarItem } from './types.ts';
6
6
  export declare const DEFAULT_TOOLBAR: ToolbarItem[];
7
7
  export declare const TOOLBAR_LABELS: Record<ToolbarItem, string>;
@@ -1,4 +1,4 @@
1
- import type { Component, VNode } from '../../client/vnode.ts';
1
+ import type { Component, VNode } from '../../ui-dom/vnode.ts';
2
2
  export interface EmptyStateProps {
3
3
  /** 图标——VNode(推荐 <Icon />)或字符串(emoji/字形);默认 Icon inbox(P3:组件内禁裸 emoji) */
4
4
  icon?: string | VNode | null;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface FieldProps {
3
3
  label?: string;
4
4
  required?: boolean;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * weifuwu/components — FileUpload
3
3
  */
4
- import type { Component } from '../../client/vnode.ts';
4
+ import type { Component } from '../../ui-dom/vnode.ts';
5
5
  export interface FileUploadProps {
6
6
  accept?: string;
7
7
  multiple?: boolean;
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * 裁剪(CS-05):不做拖拽悬浮(Resizable 可组合);回顶用 BackTop 语义更清晰。
13
13
  */
14
- import type { Component } from '../../client/vnode.ts';
14
+ import type { Component } from '../../ui-dom/vnode.ts';
15
15
  export type FloatButtonPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
16
16
  export interface FloatButtonProps {
17
17
  icon?: any;
@@ -1,4 +1,4 @@
1
- import type { Component } from '../../client/vnode.ts';
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
2
  export interface ValidationRule {
3
3
  required?: boolean;
4
4
  pattern?: RegExp;
@@ -13,7 +13,7 @@
13
13
  * 裁剪(CS-05):不做响应式断点 props(useBreakpoint 由用户驱动);
14
14
  * gutter 仅水平(垂直 gutter 低频)。
15
15
  */
16
- import type { Component } from '../../client/vnode.ts';
16
+ import type { Component } from '../../ui-dom/vnode.ts';
17
17
  export interface GridProps {
18
18
  gutter?: number;
19
19
  flex?: boolean;
@@ -4,7 +4,7 @@
4
4
  * 搜索词高亮:给定文本 + 高亮词数组 → 分词渲染 <mark>(零依赖,VNode 拼接)。
5
5
  * 配合 SearchInput/Table 搜索结果命中展示。
6
6
  */
7
- import type { Component } from '../../client/vnode.ts';
7
+ import type { Component } from '../../ui-dom/vnode.ts';
8
8
  export interface HighlightProps {
9
9
  text: string;
10
10
  query?: string | string[];
@@ -4,8 +4,8 @@
4
4
  * usePopup 组合器:hover 触发(触屏自动降级 tap)+ openDelay/closeDelay +
5
5
  * 定位/视口 clamp + Escape + portal。对应 shadcn HoverCard。
6
6
  */
7
- import type { Component } from '../../client/vnode.ts';
8
- import type { Placement } from '../../client/popup.ts';
7
+ import type { Component } from '../../ui-dom/vnode.ts';
8
+ import type { Placement } from '../../ui-dom/popup.ts';
9
9
  export type HoverCardPosition = Placement;
10
10
  export interface HoverCardProps {
11
11
  /** 富内容(任意 VNode,区别于 Tooltip 的 string) */