weifuwu 0.71.0 → 0.73.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 +85 -60
  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/{client → ui-dom}/popup.d.ts +0 -11
  127. package/dist/ui-dom/registry.d.ts +39 -0
  128. package/dist/{client → ui-dom}/render.d.ts +2 -1
  129. package/dist/ui-dom/router.d.ts +66 -0
  130. package/dist/ui-dom/serve.d.ts +28 -0
  131. package/dist/ui-dom/ssr.d.ts +56 -0
  132. package/dist/{client → ui-dom}/types.d.ts +60 -0
  133. package/dist/{client → ui-dom}/ui.d.ts +2 -0
  134. package/dist/{client → ui-dom}/vnode.d.ts +13 -12
  135. package/docs/custom-components.md +2 -0
  136. package/docs/frontend-middleware.md +3 -1
  137. package/docs/frontend-ui-dom.md +165 -0
  138. package/docs/frontend.md +3 -1
  139. package/docs/realtime.md +2 -0
  140. package/docs/saas.md +2 -0
  141. package/package.json +7 -7
  142. package/dist/client/app.d.ts +0 -26
  143. package/dist/client/error-boundary.d.ts +0 -23
  144. package/dist/client/index.d.ts +0 -54
  145. package/dist/client/index.js +0 -6
  146. package/dist/client/registry.d.ts +0 -49
  147. package/dist/client/router.d.ts +0 -27
  148. package/dist/client/type-flow.test.d.ts +0 -7
  149. /package/dist/{client → ui-dom}/ai.d.ts +0 -0
  150. /package/dist/{client → ui-dom}/browser.d.ts +0 -0
  151. /package/dist/{client → ui-dom}/diff.d.ts +0 -0
  152. /package/dist/{client → ui-dom}/focus-trap.d.ts +0 -0
  153. /package/dist/{client → ui-dom}/hydration.d.ts +0 -0
  154. /package/dist/{client → ui-dom}/i18n.d.ts +0 -0
  155. /package/dist/{client → ui-dom}/locale/en_US.d.ts +0 -0
  156. /package/dist/{client → ui-dom}/locale/zh_CN.d.ts +0 -0
  157. /package/dist/{client → ui-dom}/middleware/api.d.ts +0 -0
  158. /package/dist/{client → ui-dom}/middleware/auth.d.ts +0 -0
  159. /package/dist/{client → ui-dom}/middleware/ws.d.ts +0 -0
  160. /package/dist/{client → ui-dom}/motion.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.*` 一行接入 |
@@ -97,7 +97,7 @@ npm install weifuwu # 一个依赖,完整应用栈
97
97
 
98
98
  **async 工厂组件** — `async (ctx) => (initProps, ctx) => (props) => VNode`:工厂层声明数据(`await ctx.data.get`)、mount 初始化状态(`$`)、render 输出视图。异步只在工厂边界,mount/render 保持同步;数据经闭包注入,写数据像写同步代码。三条纪律见[核心概念 · async 组件](#核心概念)。
99
99
 
100
- **SPA/SSR/Hydration 统一透明** — 同一份路由定义(`routes`)一个组件三场景自动适配:后端 `uiSsr({ routes })` 匹配即自动 SSR(完整 HTML + `__DATA__`),客户端 `router({ routes })` + `RouteView` + `mount(..., { hydrate: true })` 按 URL 同源匹配并收养服务端 HTML(不重建、无闪跳)。`ctx.data.get` 一个 API:SSR 预取 / hydration 命中(不重复请求)/ SPA 触发 fetch。服务端直接用 `.tsx`(`weifuwu/dev` Node loader),前后端同一 JSX 运行时。
100
+ **SPA/SSR/Hydration 统一透明** — 同一份路由定义(`UIRouter`)一个组件三场景自动适配:后端 `ssrPage(router, { url })` 匹配即自动 SSR(完整 HTML + `__DATA__`),客户端 `uiServe(router, { root, hydrate: true })` 按 URL 同源匹配并收养服务端 HTML(不重建、无闪跳)。`ctx.data.get` 一个 API:SSR 预取 / hydration 命中(不重复请求)/ SPA 触发 fetch。服务端直接用 `.tsx`(`weifuwu/dev` Node loader),前后端同一 JSX 运行时。
101
101
 
102
102
  **AI 是一等公民** — 自研 OpenAI 兼容协议(`design/ai-contract.md`)+ 零依赖流式客户端 + agent 工具循环 + HITL 人工审批 + embedding 向量化。后端 `ctx.ai` 一个入口:`chat()` / `stream()` / `agent()`(`stream(messages, { emit })` emitter 抽象——事件可接任意通道,`runToResult()` 结构化结果)/ `approve()` / `embed()` / `embedMany()`;前端 `ctx.ui.useChat()`(会话语义)+ `AiChat` 组件(标准对话界面)——流式 token / 工具调用卡 / 审批卡开箱即用,协议对页面完全透明,不用 ai-sdk。
103
103
 
@@ -119,15 +119,16 @@ npm install weifuwu # 一个依赖,完整应用栈
119
119
 
120
120
  | 模式 | 适用场景 | 后端 | 客户端入口 |
121
121
  |------|---------|------|-----------|
122
- | **SPA** | 应用页(Dashboard、工具、后台) | HTML 外壳 | `mount('#root', RouteView)` |
123
- | **SSR + Hydration** | 内容页(博客、营销,需要 SEO/首屏) | `uiSsr` 一行 | `mount('#root', RouteView, { hydrate: true })` |
122
+ | **SPA** | 应用页(Dashboard、工具、后台) | HTML 外壳 | `uiServe(router, { root: '#root' })` |
123
+ | **SSR + Hydration** | 内容页(博客、营销,需要 SEO/首屏) | `ssrPage(router)` 一行 | `uiServe(router, { root: '#root', hydrate: true })` |
124
124
 
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,62 +147,67 @@ 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)
174
178
 
175
- 同一份 `routes`、同一个组件,差异只在**后端加 `uiSsr` 一行、客户端加 `hydrate` 参数**:
179
+ 同一份 `router`、同一个组件,差异只在**后端加 `ssrPage` 一行、客户端加 `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 |
@@ -322,7 +333,8 @@ cd apps/agent-platform && npm run seed && npm run dev
322
333
  | `weifuwu` | **postgres** | PostgreSQL 客户端(自研 PG v3 协议)→ `ctx.sql` | Router, DATABASE_URL |
323
334
  | `weifuwu` | **redis** | Redis 客户端(自研 RESP2 协议)→ `ctx.redis` | Router, REDIS_URL |
324
335
  | `weifuwu` | **ui** | SSR 渲染 + esbuild JS/CSS 动态编译 → `ctx.ui` | Router |
325
- | `weifuwu` | **uiSsr** | 路由级 SSR:匹配 routes自动完整 HTML + `__DATA__` + bundle | Router, ui |
336
+ | `weifuwu/ui-dom` | **uiServe** | 渲染运行时:监听 location 执行路由 VDOM 落地(`hydrate: true` 收养 SSR HTML) | UIRouter |
337
+ | `weifuwu/ui-dom` | **ssrPage** | 路由级 SSR:匹配共享 router → 自动完整 HTML + `__DATA__` | Router, ui |
326
338
  | `weifuwu` | **rateLimit** | 限流中间件(fixed/sliding,redis 多实例原子)→ `ctx.limit` | Router, redis |
327
339
  | `weifuwu` | **email** | 邮件发送(Resend/SMTP 自研/自定义适配器)→ `ctx.email` | Router |
328
340
  | `weifuwu` | **userSystem** | 用户系统(scrypt 密码哈希 + 混合会话 + 多租户感知)→ `ctx.user` / `ctx.auth` / `ctx.tenantId` + `/api/auth/*` | Router, postgres |
@@ -336,17 +348,16 @@ cd apps/agent-platform && npm run seed && npm run dev
336
348
  | `weifuwu` | **ok / badRequest / …** | HTTP 响应辅助函数(ok/badRequest/... 等 12 个) | — |
337
349
  | `weifuwu` | **parseBody** | JSON 请求体安全解析 | — |
338
350
  | 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 |
351
+ | `weifuwu/ui-dom` | **UIRouter** | 纯路由 + ctx 注入链(`use` 中间件累积类型,对齐后端 `app.use`);handler=异步组件 | — |
352
+ | `weifuwu/ui-dom` | **uiServe** | 渲染运行时:监听 location → 执行路由 → VDOM diff/patch;`hydrate: true` 收养 SSR HTML | UIRouter |
353
+ | `weifuwu/ui-dom` | **asyncComponent** | async 工厂组件:工厂层声明数据,mount/render 同步(三条纪律见[核心概念](#核心概念)) | — |
354
+ | `weifuwu/ui-dom` | **ctx.data** | 数据管道:SSR 预取 / hydration 命中 / SPA fetch(`ctx.data.get`) | uiServe |
355
+ | `weifuwu/ui-dom` | **api / auth / ws** | HTTP 客户端 / 认证 / WebSocket 中间件 | |
356
+ | `weifuwu/ui-dom` | **i18n** | 国际化中间件(运行时切换语言) | |
357
+ | `weifuwu/ui-dom` | **ssrPage / serializeData** | 服务端渲染:SSR HTML + `__DATA__` 序列化(`ctx.params` 两端同源) | |
358
+ | `weifuwu/ui-dom` | **useChat / AiChat 原语** | AI 会话(流式/工具调用/HITL) | — |
359
+ | `weifuwu/ui-dom` | **事件原语** | `usePopup` / `useDialog` / `usePresence` / `useInView` / `useScrollPosition` / `useGlobalKey` / `useDrag` / `useDragDrop` / `useAnimationEnd` / `useTween` / `useReducedMotion`(浏览器事件/动画统一入口,见 [docs/mobile.md](docs/mobile.md)) | — |
360
+ | `weifuwu/components` | **113 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/ui-dom |
350
361
  | `weifuwu/layout` | **CSS 布局** | 57 个布局原语 + 136 个工具类 + 167 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
351
362
 
352
363
  ---
@@ -358,7 +369,7 @@ cd apps/agent-platform && npm run seed && npm run dev
358
369
  | 任务 | 用 | 位置 |
359
370
  |------|-----|------|
360
371
  | 起 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) |
372
+ | 渲染页面(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
373
  | 数据持久化 | `postgres()` → `` ctx.sql`SELECT *` `` · `redis()` → `ctx.redis` | [docs/data.md](docs/data.md) |
363
374
  | 数据管道(SSR 预取/hydration/SPA) | `ctx.data.get(key)` + `asyncComponent` | [docs/frontend.md](docs/frontend.md) |
364
375
  | 用户注册/登录/会话/多租户 | `userSystem()` → `ctx.auth` + `/api/auth/*` | [docs/saas.md](docs/saas.md) |
@@ -378,6 +389,16 @@ cd apps/agent-platform && npm run seed && npm run dev
378
389
 
379
390
  ## 核心概念
380
391
 
392
+ ### 三层形态(路由 / 组件 / 异步工厂)
393
+
394
+ | 层 | 签名 | 异步 | 生命周期 |
395
+ |----|------|------|---------|
396
+ | **UIHandler**(路由) | `async (location, ctx) => VNode` | ✅ 整体 | 每次路由变化执行 |
397
+ | **Component**(组件) | `(initProps, ctx) => (props) => VNode` | ❌ 同步 | mount 一次 + render 每次 |
398
+ | **AsyncFactory**(异步组件) | `async (ctx) => (initProps, ctx) => (props) => VNode` | ✅ 只工厂 | 工厂一次(WeakMap 缓存) |
399
+
400
+ 异步只出现在两个边界——路由 handler(整页)和组件工厂(数据声明);**mount/render 永远同步**(SSR/hydration 两端一致性的根基)。`async (initProps, ctx) => ...` 是混合错形——渲染器不 await 同步组件,Promise 会被当 render 函数调用。
401
+
381
402
  ### 两阶段组件(新手必读:为什么是两层)
382
403
 
383
404
  组件 = `(initProps, ctx) => (props) => VNode`——**外层 = 初始化(只执行一次),内层 = 渲染(每次状态/props 变化时执行)**。类比:外层是对象的构造函数,内层是它的 render 方法。
@@ -404,13 +425,16 @@ const Counter = (_init, ctx) => {
404
425
  app.get('/users', (req, ctx) => { ctx.sql`SELECT *` })
405
426
  // ctx 已注入 ctx.sql
406
427
 
407
- 前端: createApp()
408
- .use(api({ baseURL: '/api' }))
409
- .use(auth())
410
- .mount('#root', App)
428
+ 前端: const router = new UIRouter()
429
+ router.use(api({ baseURL: '/api' }))
430
+ router.use(auth())
431
+ router.get('/users', async (location, ctx) => h(UsersPage, {}))
432
+ uiServe(router, { root: '#root' })
411
433
  // ctx 已注入 ctx.api, ctx.auth
412
434
  ```
413
435
 
436
+ 前端 req = `window.location`(原生对象,不包装),res = `VNode`,`uiServe` = VDOM 落地——与后端 `Request → Response`、`serve(router)` 完全同构。
437
+
414
438
  ### 状态管理
415
439
 
416
440
  | 模式 | 后端 | 前端 |
@@ -457,10 +481,10 @@ const UserProfile = asyncComponent(async (ctx) => {
457
481
  | | SPA | SSR + Hydration |
458
482
  |---|---|---|
459
483
  | 适用 | 应用页(后台、工具、Dashboard) | 内容页(博客、营销,需要 SEO/首屏) |
460
- | 后端 | HTML 外壳 | `uiSsr({ routes })` 一行(自动完整 HTML + `__DATA__`) |
461
- | 客户端 | `mount('#root', RouteView)` | `mount('#root', RouteView, { hydrate: true })` |
484
+ | 后端 | HTML 外壳 | `ssrPage(router, { url })` 一行(自动完整 HTML + `__DATA__`) |
485
+ | 客户端 | `uiServe(router, { root: '#root' })` | `uiServe(router, { root: '#root', hydrate: true })` |
462
486
 
463
- **怎么选**:默认 SPA;需要 SEO 或首屏即内容时用 SSR。两种模式可混合——一个 app 内 `uiSsr` 匹配共享路由,未匹配 `next()` 走普通 handler。
487
+ **怎么选**:默认 SPA;需要 SEO 或首屏即内容时用 SSR。两种模式可混合——一个 app 内 `ssrPage` 匹配共享 router,未匹配 `next()` 走普通 handler。
464
488
 
465
489
  ### Closeable 接口
466
490
 
@@ -488,7 +512,8 @@ README 只保留入门内容(设计理念 / 快速开始 / 核心概念 / 模
488
512
 
489
513
  | 文档 | 内容 |
490
514
  |------|------|
491
- | [docs/frontend.md](docs/frontend.md) | 前端核心:createApp / 组件模型 / 状态管理 / 条件与列表 / ref / 类型 |
515
+ | [docs/frontend.md](docs/frontend.md) | 前端核心:UIRouter / 组件模型 / 状态管理 / 条件与列表 / ref / 类型(历史 client 版见 docs/frontend.md) |
516
+ | [docs/frontend-ui-dom.md](docs/frontend-ui-dom.md) | **ui-dom**:UIRouter 纯路由 + uiServe 渲染运行时 + ctx 注入链 + components 复用 + SSR/hydration(前端唯一运行时——weifuwu/client 已删除) |
492
517
  | [docs/frontend-middleware.md](docs/frontend-middleware.md) | 前端中间件:router / api / auth / ws / i18n / ErrorBoundary / confirm / toast / ScrollLock / extendCtx |
493
518
  | [docs/components.md](docs/components.md) | 组件库(113 个组件 + 使用示例 + 组件列表) |
494
519
  | [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>;