weifuwu 0.75.0 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -53
- package/dist/ai/types.d.ts +2 -0
- package/dist/components/AiChat/AiChat.d.ts +5 -1
- package/dist/components/ApprovalCard/ApprovalCard.d.ts +5 -2
- package/dist/components/CitationCard/CitationCard.d.ts +38 -0
- package/dist/components/Command/Command.d.ts +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +1 -1
- package/dist/components/JsonSchemaForm/JsonSchemaForm.d.ts +48 -0
- package/dist/components/ReasoningBlock/ReasoningBlock.d.ts +25 -0
- package/dist/components/Select/Select.d.ts +11 -1
- package/dist/components/SessionList/SessionList.d.ts +42 -0
- package/dist/components/Tour/Tour.d.ts +1 -1
- package/dist/components/TreeSelect/TreeSelect.d.ts +3 -2
- package/dist/components/index.d.ts +10 -2
- package/dist/components/index.js +14 -14
- package/dist/components/style.css +625 -20
- package/dist/index.js +1349 -1529
- package/dist/layout/weifuwu-layout.css +9 -0
- package/dist/scheduler/index.d.ts +7 -2
- package/dist/test/client/setup.d.ts +12 -0
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui-dom/Confirm.d.ts +5 -41
- package/dist/ui-dom/Notification.d.ts +8 -70
- package/dist/ui-dom/Toast.d.ts +8 -43
- package/dist/ui-dom/hooks/chat.d.ts +11 -0
- package/dist/ui-dom/hooks/events.d.ts +30 -0
- package/dist/ui-dom/hooks/external.d.ts +20 -0
- package/dist/ui-dom/hooks/index.d.ts +30 -0
- package/dist/ui-dom/hooks/input.d.ts +33 -0
- package/dist/ui-dom/hooks/media.d.ts +17 -0
- package/dist/ui-dom/hooks/popup.d.ts +28 -0
- package/dist/ui-dom/hooks/stable.d.ts +39 -0
- package/dist/ui-dom/hooks/test/hooks.test.d.ts +1 -0
- package/dist/ui-dom/hooks/types.d.ts +77 -0
- package/dist/ui-dom/index.d.ts +19 -17
- package/dist/ui-dom/index.js +11 -11
- package/dist/ui-dom/jsx-runtime.js +1 -1
- package/dist/ui-dom/store.d.ts +24 -0
- package/dist/ui-dom/testing.d.ts +74 -0
- package/dist/ui-dom/testing.js +1 -0
- package/dist/ui-dom/testing.test.d.ts +1 -0
- package/dist/ui-dom/types.d.ts +55 -50
- package/dist/ui-dom/use-chat.d.ts +19 -14
- package/dist/ui-dom/vdom/build.d.ts +41 -0
- package/dist/ui-dom/vdom/diff.d.ts +33 -0
- package/dist/ui-dom/vdom/hydration.d.ts +17 -0
- package/dist/ui-dom/vdom/index.d.ts +23 -0
- package/dist/ui-dom/vdom/mount.d.ts +58 -0
- package/dist/ui-dom/vdom/registry.d.ts +27 -0
- package/dist/ui-dom/vdom/render.d.ts +15 -0
- package/dist/ui-dom/vdom/serve.d.ts +30 -0
- package/dist/ui-dom/vdom/ssr.d.ts +44 -0
- package/dist/ui-dom/vnode.d.ts +19 -31
- package/docs/components-map.md +18 -1
- package/docs/components.md +12 -7
- package/docs/custom-components.md +90 -60
- package/docs/examples.md +35 -41
- package/docs/frontend-middleware.md +3 -4
- package/docs/frontend-ui-dom.md +21 -18
- package/docs/frontend.md +243 -168
- package/docs/layout.md +2 -2
- package/docs/mobile.md +2 -2
- package/docs/realtime.md +8 -3
- package/package.json +5 -1
- package/dist/ui/ssr.d.ts +0 -35
- package/dist/ui-dom/diff.d.ts +0 -28
- package/dist/ui-dom/focus-trap.d.ts +0 -4
- package/dist/ui-dom/hydration.d.ts +0 -13
- package/dist/ui-dom/reactive.d.ts +0 -6
- package/dist/ui-dom/registry.d.ts +0 -27
- package/dist/ui-dom/render.d.ts +0 -46
- package/dist/ui-dom/scroll-lock.d.ts +0 -5
- package/dist/ui-dom/serve.d.ts +0 -28
- package/dist/ui-dom/ssr.d.ts +0 -57
- package/dist/ui-dom/ui.d.ts +0 -78
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# weifuwu
|
|
2
2
|
|
|
3
|
-
**自托管全栈框架** — 一个 npm 包 = 后端 HTTP + 前端 VDOM +
|
|
3
|
+
**自托管全栈框架** — 一个 npm 包 = 后端 HTTP + 前端 VDOM + 113 组件 + CSS 设计系统 + SaaS 地基(认证 / 消息 / 队列 / AI)。全自研、零构建、消灭样板。
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install weifuwu # 一个依赖,完整应用栈
|
|
@@ -24,16 +24,16 @@ npm install weifuwu # 一个依赖,完整应用栈
|
|
|
24
24
|
|----|------|------|
|
|
25
25
|
| 后端 | `weifuwu` | Trie 路由 / 中间件链 / serve / 自研 PG+Redis / SSR / GraphQL / WebSocket |
|
|
26
26
|
| 前端 | `weifuwu/ui-dom` | **UIRouter(纯路由 + ctx 注入链)+ uiServe(渲染运行时)+ SSR/hydration**——handler=异步组件 / 中间件两阶段 / ctx.params 对齐后端;**weifuwu/components 直接复用**(VNode 契约唯一来源 ui-dom,见 `docs/frontend-ui-dom.md`) |
|
|
27
|
-
| 组件 | `weifuwu/components` |
|
|
28
|
-
| 样式 | `weifuwu/layout` |
|
|
27
|
+
| 组件 | `weifuwu/components` | 113 个 HTML 原语组件(表单/表格/弹层/AiChat…),引用 `--wf-*` 主题变量 |
|
|
28
|
+
| 样式 | `weifuwu/layout` | 58 布局原语 + 136 工具类 + 167 主题 Token,零自定义 CSS 文件 |
|
|
29
29
|
| SaaS 地基 | 随包内置 | rateLimit / email / userSystem / messager / queue / ai → `ctx.*` 一行接入 |
|
|
30
30
|
|
|
31
31
|
> ⚠️ **注意:前后端都有 `ctx.ui`,但用途完全不同**
|
|
32
32
|
> - **后端** `ctx.ui`(SSR/编译):`ctx.ui.html`(HTML 模板)、`ctx.ui.js`(TSX→JS 动态编译)、`ctx.ui.css`(CSS 编译)、`ctx.ui.ssr`(组件 SSR)、`ctx.ui.ssrData`(数据序列化)
|
|
33
|
-
> - **前端** `ctx.ui`(渲染引擎,
|
|
34
|
-
> -
|
|
35
|
-
> - 状态:`useControlled()`(受控/非受控)/ `useStableRef()`(稳定 ref
|
|
36
|
-
> - 弹层:`usePopup()
|
|
33
|
+
> - **前端** `ctx.ui`(渲染引擎,20+ hooks):
|
|
34
|
+
> - 渲染:`render()`(唯一触发——render-only)/ `selfId()`(跨组件精准刷新)
|
|
35
|
+
> - 状态:`useControlled()`(受控/非受控)/ `useStableRef()`(稳定 ref)/ `useExternal()`(共享状态订阅)
|
|
36
|
+
> - 弹层:`usePopup()`(统一能力层——锚定浮层 + 会话级模态)/ `usePopupPosition()`(定位)
|
|
37
37
|
> - 事件:`useInView()` / `useScrollPosition()` / `useMedia()` / `useBreakpoint()` / `useGlobalKey()` / `useDrag()` / `useDragDrop()` / `useHoverCapable()` / `useLongPress()` / `useVisualViewport()`
|
|
38
38
|
> - 动画:`useAnimationEnd()`(完成回调)/ `usePresence()`(显隐状态机)/ `useTween()`(数值补间)/ `useReducedMotion()`(偏好感知)
|
|
39
39
|
> - AI/数据:`useChat()`(AI 会话)/ `useAsync()`(异步取数)
|
|
@@ -89,13 +89,13 @@ npm install weifuwu # 一个依赖,完整应用栈
|
|
|
89
89
|
|
|
90
90
|
**零运行时依赖** — 前端无 npm 运行时依赖(自研 VDOM,不引入 Virtual DOM 库、rxjs、immer 等)。后端仅依赖 `esbuild`(TSX→JS 编译)+ `graphql` + `ws`(语言/协议本身)——**数据库客户端(PostgreSQL/Redis 协议)、GraphQL schema 工具全部自研**。esbuild 作为运行时依赖随 `npm install weifuwu` 自动安装,`ctx.ui.js()` 开箱即用。
|
|
91
91
|
|
|
92
|
-
**两阶段组件模型** — 组件 = `(initProps, ctx) => (props) => VNode
|
|
92
|
+
**两阶段组件模型** — 组件 = `async (initProps, ctx) => (props) => Promise<VNode>`。外层工厂只执行一次(mount,可 await 数据),内层 renderFn 每次状态/props 变化时执行(强制异步)。无 class、无 `this`、无 Hook——**位置即语义**:外层天生只跑一次,没有 hooks 规则、没有依赖数组、没有闭包陷阱(详解见[核心概念](#核心概念))。
|
|
93
93
|
|
|
94
|
-
**
|
|
94
|
+
**render-only 确定性渲染** — 渲染唯一触发 `ctx.ui.render()`(闭包绑定组件),状态是普通对象(`let` + `render()`);跨组件共享用 `createStore` + `ctx.ui.useExternal()`。行为可静态推导,无隐式触发(详见[组件库](docs/components.md))。
|
|
95
95
|
|
|
96
96
|
**中间件注入一切** — 后端和前端共用同一理念:中间件向 `ctx` 注入能力(`ctx.sql` / `ctx.redis` / `ctx.api` / `ctx.auth` / `ctx.i18n` / `ctx.limit` / `ctx.email` / `ctx.queue` / `ctx.ai` / `ctx.msg` 等),Handler/组件从 `ctx` 读取。
|
|
97
97
|
|
|
98
|
-
**async 工厂组件** — `async (
|
|
98
|
+
**async 工厂组件** — `async (initProps, ctx) => (props) => Promise<VNode>`(weifuwu **唯一组件形态**——同步组件已不支持):工厂层声明数据(`await ctx.data.get`)、mount 初始化状态(`let` + `render()`)、render 输出视图。异步在工厂边界与 renderFn,数据经闭包注入,写数据像写同步代码。三条纪律见[核心概念 · async 组件](#核心概念)。
|
|
99
99
|
|
|
100
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
|
|
|
@@ -109,7 +109,7 @@ npm install weifuwu # 一个依赖,完整应用栈
|
|
|
109
109
|
|
|
110
110
|
**自研数据层** — `ctx.sql`(PG v3 协议)与 `ctx.redis`(RESP2 协议)为**自研客户端**:确定性输出、行为可预测、统一错误模型。jsonb 自动解码、TTL 安全 API、schema 写前校验——高频痛点(双重编码/parseRow 样板/`'EX'` 参数顺序)从根上消除。
|
|
111
111
|
|
|
112
|
-
> **实践验证**:多租户 AI 平台(`apps/agent-platform`——14 页 + 部门聊天 + 知识库 + HITL 审批)已完全运行在框架上:auth(userSystem)/ AI 引擎(ai)/ 实时消息(messager)/ UI(
|
|
112
|
+
> **实践验证**:多租户 AI 平台(`apps/agent-platform`——14 页 + 部门聊天 + 知识库 + HITL 审批)已完全运行在框架上:auth(userSystem)/ AI 引擎(ai)/ 实时消息(messager)/ UI(113 组件)/ 数据管道(ctx.api)零自研替代。框架哲学(中间件注入、诚实裁剪、机制与策略分离)经受住了真实复杂应用的检验——这也是我们确定「哪些进框架、哪些留应用层」的依据。
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
@@ -133,7 +133,7 @@ const app = new UIRouter()
|
|
|
133
133
|
// async 组件(原生):await 数据 → 返回视图(外层初始化,内层渲染)
|
|
134
134
|
const Home = async (_init, ctx) => {
|
|
135
135
|
const msg = await ctx.data.get('/api/hello') // 数据管道:一个 API 三场景
|
|
136
|
-
return (props) => <h1>{msg.msg}</h1>
|
|
136
|
+
return async (props) => <h1>{msg.msg}</h1>
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
app.get('/', async () => <Home />) // handler = 异步组件
|
|
@@ -225,7 +225,7 @@ uiServe(app, { root: '#root', hydrate: true })
|
|
|
225
225
|
### 30 秒体验(跑现有 demo)
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
|
-
# ① 组件 cheatsheet——
|
|
228
|
+
# ① 组件 cheatsheet——113 组件全部可交互预览(零依赖,5 秒起)
|
|
229
229
|
cd apps/components-demo && node server.ts
|
|
230
230
|
# 打开 http://localhost:3000
|
|
231
231
|
|
|
@@ -275,25 +275,24 @@ cd apps/agent-platform && npm run seed && npm run dev
|
|
|
275
275
|
import { UIRouter, uiServe, h } from 'weifuwu/ui-dom'
|
|
276
276
|
import { Card, Button, Badge } from 'weifuwu/components'
|
|
277
277
|
|
|
278
|
-
// 组件 = (initProps, ctx) => (props) => VNode
|
|
279
|
-
const Counter = (
|
|
280
|
-
|
|
281
|
-
$.count = 0 // mount 初始化
|
|
278
|
+
// 组件 = async (initProps, ctx) => (props) => Promise<VNode>(render-only:改状态后 ctx.ui.render())
|
|
279
|
+
const Counter = async (_init, ctx) => {
|
|
280
|
+
let count = 0 // mount 初始化
|
|
282
281
|
|
|
283
282
|
return () =>
|
|
284
283
|
h(Card, { variant: 'default', padding: 'lg' },
|
|
285
284
|
h('h2', { style: { textAlign: 'center', margin: 0 } }, '⚡ Weifuwu'),
|
|
286
285
|
h('div', { style: { fontSize: '4rem', fontWeight: 600, textAlign: 'center' } },
|
|
287
|
-
String(
|
|
286
|
+
String(count)),
|
|
288
287
|
h('div', { style: { textAlign: 'center', marginTop: '1rem' } },
|
|
289
288
|
h(Badge, {
|
|
290
|
-
variant:
|
|
291
|
-
},
|
|
289
|
+
variant: count % 2 === 0 ? 'success' : 'warning'
|
|
290
|
+
}, count % 2 === 0 ? '偶数' : '奇数')),
|
|
292
291
|
h('hr', { style: { margin: '1rem 0', border: 'none', borderTop: '1px solid #eee' } }),
|
|
293
292
|
h('div', { style: { display: 'flex', gap: '0.5rem', justifyContent: 'center' } },
|
|
294
|
-
h(Button, { variant: 'secondary', onClick: () =>
|
|
295
|
-
h(Button, { variant: 'danger', onClick: () =>
|
|
296
|
-
h(Button, { variant: 'primary', onClick: () =>
|
|
293
|
+
h(Button, { variant: 'secondary', onClick: () => { count--; ctx.ui.render() } }, '➖ 减 1'),
|
|
294
|
+
h(Button, { variant: 'danger', onClick: () => { count = 0; ctx.ui.render() } }, '↺ 重置'),
|
|
295
|
+
h(Button, { variant: 'primary', onClick: () => { count++; ctx.ui.render() } }, '➕ 加 1'),
|
|
297
296
|
),
|
|
298
297
|
)
|
|
299
298
|
}
|
|
@@ -314,8 +313,8 @@ cd apps/agent-platform && npm run seed && npm run dev
|
|
|
314
313
|
| 资源 | CDN 地址 | 说明 |
|
|
315
314
|
|------|---------|------|
|
|
316
315
|
| `weifuwu/ui-dom` | `https://unpkg.com/weifuwu@latest/dist/ui-dom/index.js` | 前端运行时(UIRouter, uiServe, h, 状态管理等) |
|
|
317
|
-
| `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` |
|
|
318
|
-
| `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 167 个主题 Token +
|
|
316
|
+
| `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 113 个 UI 组件(Button, Card, Table, Modal, Icon 等) |
|
|
317
|
+
| `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 167 个主题 Token + 58 个布局原语 + 136 个工具类 |
|
|
319
318
|
| 独立布局系统 | `https://unpkg.com/weifuwu@latest/dist/layout/weifuwu-layout.css` | 仅 CSS 布局,不依赖 JS |
|
|
320
319
|
|
|
321
320
|
|
|
@@ -356,9 +355,9 @@ cd apps/agent-platform && npm run seed && npm run dev
|
|
|
356
355
|
| `weifuwu/ui-dom` | **i18n** | 国际化中间件(运行时切换语言) | — |
|
|
357
356
|
| `weifuwu/ui-dom` | **ssrPage / serializeData** | 服务端渲染:SSR HTML + `__DATA__` 序列化(`ctx.params` 两端同源) | — |
|
|
358
357
|
| `weifuwu/ui-dom` | **useChat / AiChat 原语** | AI 会话(流式/工具调用/HITL) | — |
|
|
359
|
-
| `weifuwu/ui-dom` | **事件原语** | `usePopup
|
|
360
|
-
| `weifuwu/components` | **
|
|
361
|
-
| `weifuwu/layout` | **CSS 布局** |
|
|
358
|
+
| `weifuwu/ui-dom` | **事件原语** | `usePopup`(统一弹窗能力层)/ `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 |
|
|
360
|
+
| `weifuwu/layout` | **CSS 布局** | 58 个布局原语 + 136 个工具类 + 167 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
|
|
362
361
|
|
|
363
362
|
---
|
|
364
363
|
|
|
@@ -380,8 +379,8 @@ cd apps/agent-platform && npm run seed && npm run dev
|
|
|
380
379
|
| 后台任务/定时 | `queue()` → `ctx.queue` · `scheduler()` → `ctx.schedule/cron` | [docs/saas.md](docs/saas.md) |
|
|
381
380
|
| AI 对话 / Agent / HITL 审批 | `ai()` → `ctx.ai` + `ctx.ui.useChat()` + `AiChat` | [docs/saas.md](docs/saas.md) |
|
|
382
381
|
| GraphQL / WebSocket | `app.graphql(handler)` · `app.ws(path, handler)` | [docs/realtime.md](docs/realtime.md) |
|
|
383
|
-
| 前端 UI 组件 | `weifuwu/components`(
|
|
384
|
-
| 布局/主题/暗色 | `weifuwu/layout`(
|
|
382
|
+
| 前端 UI 组件 | `weifuwu/components`(113 个:Button/Table/Modal/AiChat/...) | [docs/components.md](docs/components.md) |
|
|
383
|
+
| 布局/主题/暗色 | `weifuwu/layout`(58 原语 + 136 工具类 + 167 Token) | [docs/layout.md](docs/layout.md) |
|
|
385
384
|
| 样式定制(零自定义 CSS) | `--wf-*` 变量覆盖 + 组件定制钩子 | [docs/styling.md](docs/styling.md) |
|
|
386
385
|
| 移动端适配(tap/长按/键盘/弹层) | `usePopup` / `useHoverCapable` / `useLongPress` / `useVisualViewport` | [docs/mobile.md](docs/mobile.md) |
|
|
387
386
|
| 前后端类型安全中间件 | `createMiddleware`(声明注入即类型化) | [docs/server.md](docs/server.md) |
|
|
@@ -390,27 +389,25 @@ cd apps/agent-platform && npm run seed && npm run dev
|
|
|
390
389
|
|
|
391
390
|
## 核心概念
|
|
392
391
|
|
|
393
|
-
### 三层形态(路由 /
|
|
392
|
+
### 三层形态(路由 / 组件 / async 组件工厂)
|
|
394
393
|
|
|
395
394
|
| 层 | 签名 | 异步 | 生命周期 |
|
|
396
395
|
|----|------|------|---------|
|
|
397
396
|
| **UIHandler**(路由) | `async (location, ctx) => VNode` | ✅ 整体 | 每次路由变化执行 |
|
|
398
|
-
| **Component
|
|
399
|
-
| **AsyncComponent**(async 组件) | `async (initProps, ctx) => (props) => VNode` | ✅ 只工厂 | 工厂按实例(diff 传递 `_asyncDef`,补全不重跑) |
|
|
397
|
+
| **Component**(唯一形态) | `async (initProps, ctx) => (props) => Promise<VNode>` | ✅ 工厂 + renderFn | mount 一次 + render 每次;同步组件已不支持(类型强制 Promise) |
|
|
400
398
|
|
|
401
|
-
|
|
399
|
+
异步只在两个边界——路由 handler(整页)和组件工厂(数据声明)+ renderFn(强制异步)。渲染器按「返回值 instanceof Promise」统一判别:主路径 `buildVNode` async 预构建(await 全部工厂,兄弟并行)→ 原子落地(无占位、无补全回调);运行时首次挂载的 async 组件同样在 buildVNode 阶段 await;骨架屏 `uiServe({ loading })` + `handle.ready`。
|
|
402
400
|
### 两阶段组件(新手必读:为什么是两层)
|
|
403
401
|
|
|
404
|
-
组件 = `(initProps, ctx) => (props) => VNode
|
|
402
|
+
组件 = `async (initProps, ctx) => (props) => Promise<VNode>`——**外层 = 初始化(只执行一次,可 await 数据),内层 = 渲染(每次状态/props 变化时执行,强制异步)**。类比:外层是对象的构造函数,内层是它的 render 方法。
|
|
405
403
|
|
|
406
404
|
```tsx
|
|
407
|
-
const Counter = (_init, ctx) => {
|
|
408
|
-
// 外层(mount
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
<button onClick={() => $.count++}>{$.count}</button>
|
|
405
|
+
const Counter = async (_init, ctx) => {
|
|
406
|
+
// 外层(mount):只跑一次——初始化状态、订阅、定时器(可 await 数据)
|
|
407
|
+
let count = 0
|
|
408
|
+
return async (props) =>
|
|
409
|
+
// 内层(render):每次变化执行(强制异步)——读状态输出视图(render-only:改状态后显式 render())
|
|
410
|
+
<button onClick={() => { count++; ctx.ui.render() }}>{count}</button>
|
|
414
411
|
}
|
|
415
412
|
```
|
|
416
413
|
|
|
@@ -441,7 +438,7 @@ const Counter = (_init, ctx) => {
|
|
|
441
438
|
|------|------|------|
|
|
442
439
|
| 注入 | 中间件注入 ctx.field | 中间件注入 ctx.field |
|
|
443
440
|
| 读取 | handler 读取 ctx | 组件读取 ctx |
|
|
444
|
-
| 渲染 | 返回 Response | `ctx.ui.render()`
|
|
441
|
+
| 渲染 | 返回 Response | `ctx.ui.render()` 触发局部 VDOM patch(render-only);共享状态 `createStore` + `useExternal` |
|
|
445
442
|
|
|
446
443
|
### async 组件(三条纪律)
|
|
447
444
|
|
|
@@ -450,12 +447,11 @@ async 组件让"拿数据渲染页面"像写同步代码——签名与同步组
|
|
|
450
447
|
```tsx
|
|
451
448
|
const UserProfile = async (_init, ctx) => {
|
|
452
449
|
const user = await ctx.data.get(`/api/user/${ctx.params.id}`) // ① 工厂层:声明数据(三场景自动)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
return (props) =>
|
|
450
|
+
let liked = false // ② mount:客户端状态(render-only)
|
|
451
|
+
return async (props) =>
|
|
456
452
|
h('div', {},
|
|
457
453
|
h('p', {}, user.name), // 服务端状态(闭包,SSR 进 HTML)
|
|
458
|
-
h('button', { onClick: () =>
|
|
454
|
+
h('button', { onClick: () => { liked = !liked; ctx.ui.render() } }, liked ? '❤️' : '🤍'))
|
|
459
455
|
}
|
|
460
456
|
```
|
|
461
457
|
|
|
@@ -464,14 +460,13 @@ const UserProfile = async (_init, ctx) => {
|
|
|
464
460
|
| 纪律 | 反例 | 正确 |
|
|
465
461
|
|---|---|---|
|
|
466
462
|
| ① 数据 key 必须含维度 | `ctx.data.get('/api/user')`——`/users/1 → /users/2` 导航命中旧缓存 | `ctx.data.get(\`/api/user/${ctx.params.id}\`)` |
|
|
467
|
-
| ②
|
|
468
|
-
| ③ 初始状态必须确定性 |
|
|
463
|
+
| ② 会变的数据放组件状态 | `const count = data.count`——点击永不更新 | `let count = data.count` + 交互后 `ctx.ui.render()`(初始值 seed 自服务端数据) |
|
|
464
|
+
| ③ 初始状态必须确定性 | `let w = window.innerWidth`——SSR/hydration mismatch | 用服务端数据 seed,交互后再测 |
|
|
469
465
|
|
|
470
466
|
**常见坑**:
|
|
471
467
|
- 工厂按**实例**执行(N 处实例 = N 次工厂调用)——数据必须走 `ctx.data`(自带缓存 + 并发合并,重复执行零成本);禁止副作用/昂贵操作裸写工厂
|
|
472
468
|
- 闭包数据是页面加载时的**快照**——路由参数变化靠工厂重跑刷新(key 变 → 缓存 miss → 重新取数)
|
|
473
|
-
- **个性化数据不进 `ctx.data`**——SSR
|
|
474
|
-
- **占位显示**:async 组件未 resolve 时渲染 `Placeholder`——无边界显示 null;`<Suspense fallback={...}>` 边界内占位处显示 fallback(可选,子树内任意深度 async 组件共享)
|
|
469
|
+
- **个性化数据不进 `ctx.data`**——SSR 会把工厂取数结果序列化给所有客户端,会话/用户相关数据留在客户端 `let` + fetch + `render()`
|
|
475
470
|
|
|
476
471
|
### 渲染策略:SPA 还是 SSR?
|
|
477
472
|
|
|
@@ -514,8 +509,8 @@ README 只保留入门内容(设计理念 / 快速开始 / 核心概念 / 模
|
|
|
514
509
|
| [docs/frontend.md](docs/frontend.md) | 前端核心:应用引导(UIRouter+uiServe)/ 组件模型 / 异步组件 / 状态管理 / 条件与列表 / ref / 类型(weifuwu/client 已并入 ui-dom) |
|
|
515
510
|
| [docs/frontend-ui-dom.md](docs/frontend-ui-dom.md) | **ui-dom**:UIRouter 纯路由 + uiServe 渲染运行时 + ctx 注入链 + components 复用 + SSR/hydration(前端唯一运行时——weifuwu/client 已删除) |
|
|
516
511
|
| [docs/frontend-middleware.md](docs/frontend-middleware.md) | 前端中间件:router / api / auth / ws / i18n / ErrorBoundary / confirm / toast / ScrollLock / extendCtx |
|
|
517
|
-
| [docs/components.md](docs/components.md) | 组件库(
|
|
518
|
-
| [docs/layout.md](docs/layout.md) | 布局系统:
|
|
512
|
+
| [docs/components.md](docs/components.md) | 组件库(113 个组件 + 使用示例 + 组件列表) |
|
|
513
|
+
| [docs/layout.md](docs/layout.md) | 布局系统:58 个布局原语 + 136 个工具类 + 167 个主题 Token |
|
|
519
514
|
| [docs/styling.md](docs/styling.md) | 样式定制指南:零自定义 CSS 模式 / 暗色 / 组件级覆盖 / 作用域主题 |
|
|
520
515
|
|
|
521
516
|
### 通用
|
package/dist/ai/types.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export interface WfUsage {
|
|
|
22
22
|
export interface WfDone {
|
|
23
23
|
content: string;
|
|
24
24
|
usage?: WfUsage;
|
|
25
|
+
/** thinking 模式的推理过程(reasoning_content),收尾时一次性下发(v1 不进流式) */
|
|
26
|
+
reasoning?: string;
|
|
25
27
|
}
|
|
26
28
|
export type WfErrorCode = 'auth_failed' | 'rate_limited' | 'context_length' | 'timeout' | 'provider_error' | 'invalid_request' | 'unsupported' | 'aborted';
|
|
27
29
|
export interface WfError {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import type { Component } from '../../ui-dom/vnode.ts';
|
|
22
22
|
import type { UseChatHandle, UiMessage } from '../../ui-dom/use-chat.ts';
|
|
23
|
-
import type { WfError, WfUsage } from '../../ai/types.ts';
|
|
23
|
+
import type { WfError, WfUsage, WfApprovalRequest } from '../../ai/types.ts';
|
|
24
|
+
import type { JsonSchema } from '../JsonSchemaForm/JsonSchemaForm.ts';
|
|
24
25
|
export interface AiChatLabels {
|
|
25
26
|
send: string;
|
|
26
27
|
stop: string;
|
|
@@ -43,6 +44,9 @@ export interface AiChatProps {
|
|
|
43
44
|
renderMessage?: (msg: UiMessage) => any;
|
|
44
45
|
/** 工具参数渲染(透传 ToolCallCard) */
|
|
45
46
|
renderToolArgs?: (args: Record<string, unknown>) => any;
|
|
47
|
+
/** 审批修改参数:按审批请求返回工具参数 schema(返回 undefined 则审批卡无修改入口;
|
|
48
|
+
* 提交修改后参数 → chat.approve('modified', …)——后端按 modifiedArgs 执行) */
|
|
49
|
+
approveSchema?: (request: WfApprovalRequest) => JsonSchema | undefined;
|
|
46
50
|
/** 键盘弹起时输入区 fixed 抬升(全屏 chat 布局用;内联卡片默认 false——原生聚焦滚动已够) */
|
|
47
51
|
raiseOnKeyboard?: boolean;
|
|
48
52
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Component } from '../../ui-dom/vnode.ts';
|
|
2
|
+
import { type JsonSchema } from '../JsonSchemaForm/JsonSchemaForm.ts';
|
|
2
3
|
import type { WfApprovalRequest } from '../../ai/types.ts';
|
|
3
4
|
/**
|
|
4
5
|
* ApprovalCard — 人工审批卡片(wf: 协议 §4.5 交互原语)
|
|
@@ -20,13 +21,15 @@ export interface ApprovalCardProps {
|
|
|
20
21
|
request: WfApprovalRequest;
|
|
21
22
|
/** 卡片状态(默认 pending) */
|
|
22
23
|
status?: ApprovalStatus;
|
|
23
|
-
/** 用户点"允许" */
|
|
24
|
-
onApprove?: () => void;
|
|
24
|
+
/** 用户点"允许"(modified 决策时带修改后参数——父层据此选 decision) */
|
|
25
|
+
onApprove?: (modifiedArgs?: Record<string, unknown>) => void;
|
|
25
26
|
/** 用户点"拒绝",note 为可选备注(进 agent 上下文) */
|
|
26
27
|
onReject?: (note?: string) => void;
|
|
27
28
|
/** 自定义详情渲染(默认显示 name + args) */
|
|
28
29
|
renderDetail?: (request: WfApprovalRequest) => any;
|
|
29
30
|
/** 提交中(按钮禁用 + 文案反馈,防连点) */
|
|
30
31
|
loading?: boolean;
|
|
32
|
+
/** 工具参数 schema——提供时渲染「修改参数」入口(JsonSchemaForm,预填 request.args),提交带修改后参数 */
|
|
33
|
+
argsSchema?: JsonSchema;
|
|
31
34
|
}
|
|
32
35
|
export declare const ApprovalCard: Component<ApprovalCardProps>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Component } from '../../ui-dom/vnode.ts';
|
|
2
|
+
import type { WfuiContext } from '../../ui-dom/types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* CitationCard — RAG 检索引用展示(AI 差异化)
|
|
5
|
+
*
|
|
6
|
+
* AI 回复的引用来源列表:折叠「引用 N 条」头部 + 展开条目列表
|
|
7
|
+
* (序号 + 标题 + 来源 + 片段 + 可选链接)。手动优先(let + render())。
|
|
8
|
+
*
|
|
9
|
+
* ```tsx
|
|
10
|
+
* <CitationCard
|
|
11
|
+
* items={[{ id, title, source, snippet, url? }]}
|
|
12
|
+
* maxVisible={3}
|
|
13
|
+
* onOpen={(c) => openDoc(c.id)}
|
|
14
|
+
* />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export interface Citation {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
/** 来源元信息(文档路径/域名等) */
|
|
21
|
+
source?: string;
|
|
22
|
+
/** 原文片段(裁剪:不做全文展开——片段即展示) */
|
|
23
|
+
snippet: string;
|
|
24
|
+
/** 可点击链接(无 onOpen 时新窗口打开) */
|
|
25
|
+
url?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface CitationCardProps {
|
|
28
|
+
items: Citation[];
|
|
29
|
+
/** 折叠头文案(默认「引用来源」) */
|
|
30
|
+
label?: string;
|
|
31
|
+
/** 折叠时最多显示条数(默认 3;溢出显示 +N 汇总条目) */
|
|
32
|
+
maxVisible?: number;
|
|
33
|
+
/** 初始展开(默认折叠) */
|
|
34
|
+
defaultExpanded?: boolean;
|
|
35
|
+
/** 点击条目回调(提供时不渲染链接,由调用方处理跳转/打开) */
|
|
36
|
+
onOpen?: (citation: Citation) => void;
|
|
37
|
+
}
|
|
38
|
+
export declare const CitationCard: Component<CitationCardProps, WfuiContext>;
|
|
@@ -18,5 +18,5 @@ export interface CommandProps {
|
|
|
18
18
|
/** 全局快捷键,如 'mod+k'(cmd/ctrl + k);null 关闭全局监听 */
|
|
19
19
|
globalShortcut?: string | null;
|
|
20
20
|
}
|
|
21
|
-
/** 命令面板(对应 shadcn Command
|
|
21
|
+
/** 命令面板(对应 shadcn Command):usePopup mask 全屏遮罩 + 搜索 + 键盘流(↑↓ Enter Escape)+ Cmd+K 全局快捷键 */
|
|
22
22
|
export declare const Command: Component<CommandProps>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Component } from '../../ui-dom/vnode.ts';
|
|
2
|
+
import type { WfuiContext } from '../../ui-dom/types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* JsonSchemaForm — JSON Schema(对象子集)→ 参数输入表单(零依赖)
|
|
5
|
+
*
|
|
6
|
+
* AI 场景参数输入面:工具调用参数(ToolCallCard 只展示,本组件负责输入)、
|
|
7
|
+
* 审批 modified 决策的取参来源、Agent 配置页 schema 驱动表单。
|
|
8
|
+
*
|
|
9
|
+
* 类型映射:string→Input / number|integer→InputNumber / boolean→Switch /
|
|
10
|
+
* string+enum→Select / object→嵌套折叠区(递归)/ array→列表 + 添加/删除。
|
|
11
|
+
*
|
|
12
|
+
* 值管理:内部 state(非受控),`value` 仅作初始值——输入回流来自内部,
|
|
13
|
+
* 无受控回流焦点问题(§5.3);`onChange` 每次编辑通知(不回流控制)。
|
|
14
|
+
* 校验(submit 时):required / enum / min-max / minLength-maxLength,
|
|
15
|
+
* 错误展示在字段 error,不触发 onSubmit。
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <JsonSchemaForm schema={tool.parameters} value={args} onSubmit={run} submitLabel="执行" />
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export interface JsonSchema {
|
|
22
|
+
type?: 'object' | 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'null';
|
|
23
|
+
title?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
properties?: Record<string, JsonSchema>;
|
|
26
|
+
required?: string[];
|
|
27
|
+
enum?: (string | number)[];
|
|
28
|
+
items?: JsonSchema;
|
|
29
|
+
default?: unknown;
|
|
30
|
+
minimum?: number;
|
|
31
|
+
maximum?: number;
|
|
32
|
+
minLength?: number;
|
|
33
|
+
maxLength?: number;
|
|
34
|
+
/** 不支持的 schema 关键字($ref 等)——诚实裁剪:告警 + 降级文本输入 */
|
|
35
|
+
$ref?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface JsonSchemaFormProps {
|
|
38
|
+
/** 顶层对象 schema(type: 'object' + properties) */
|
|
39
|
+
schema: JsonSchema;
|
|
40
|
+
/** 初始值(非受控语义);内部状态由编辑驱动 */
|
|
41
|
+
value?: Record<string, any>;
|
|
42
|
+
/** 每次编辑通知(父层可读最新值;不回流控制) */
|
|
43
|
+
onChange?: (values: Record<string, any>) => void;
|
|
44
|
+
/** 提交(校验通过才触发);不传则不渲染提交按钮 */
|
|
45
|
+
onSubmit?: (values: Record<string, any>) => void;
|
|
46
|
+
submitLabel?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare const JsonSchemaForm: Component<JsonSchemaFormProps, WfuiContext>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Component } from '../../ui-dom/vnode.ts';
|
|
2
|
+
import type { WfuiContext } from '../../ui-dom/types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* ReasoningBlock — CoT 推理过程折叠展示(AI 差异化)
|
|
5
|
+
*
|
|
6
|
+
* DeepSeek thinking 模式的 reasoning_content 展示层:折叠「已思考」头部,
|
|
7
|
+
* 点击展开推理文本。流式(streaming)时头部带脉冲指示。
|
|
8
|
+
*
|
|
9
|
+
* 手动优先(组件库纪律):let expanded + render(),无 $。
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <ReasoningBlock content={m.reasoning} streaming={m.status === 'streaming'} />
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export interface ReasoningBlockProps {
|
|
16
|
+
/** 推理文本(reasoning_content) */
|
|
17
|
+
content: string;
|
|
18
|
+
/** 初始展开(默认折叠) */
|
|
19
|
+
defaultExpanded?: boolean;
|
|
20
|
+
/** 折叠头部文案(默认「已思考」) */
|
|
21
|
+
label?: string;
|
|
22
|
+
/** 流式中(头部脉冲指示) */
|
|
23
|
+
streaming?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare const ReasoningBlock: Component<ReasoningBlockProps, WfuiContext>;
|
|
@@ -4,10 +4,20 @@ export interface SelectOption {
|
|
|
4
4
|
label: string;
|
|
5
5
|
disabled?: boolean;
|
|
6
6
|
}
|
|
7
|
+
/** 选项组(optgroup):label + 组内选项 */
|
|
8
|
+
export interface SelectOptionGroup {
|
|
9
|
+
label: string;
|
|
10
|
+
options: SelectOption[];
|
|
11
|
+
}
|
|
12
|
+
/** 选项列表:平铺项与分组可混用 */
|
|
13
|
+
export type SelectOptions = (SelectOption | SelectOptionGroup)[];
|
|
14
|
+
export declare function isOptionGroup(o: SelectOption | SelectOptionGroup): o is SelectOptionGroup;
|
|
15
|
+
/** 展平(键盘索引 / 选中查找用);保持顺序 */
|
|
16
|
+
export declare function flattenOptions(opts: SelectOptions | undefined): SelectOption[];
|
|
7
17
|
export interface SelectProps {
|
|
8
18
|
label?: string;
|
|
9
19
|
value?: string | string[];
|
|
10
|
-
options?:
|
|
20
|
+
options?: SelectOptions;
|
|
11
21
|
placeholder?: string;
|
|
12
22
|
required?: boolean;
|
|
13
23
|
disabled?: boolean;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Component } from '../../ui-dom/vnode.ts';
|
|
2
|
+
import type { WfuiContext } from '../../ui-dom/types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* SessionList — 侧栏会话管理列表(AI 差异化)
|
|
5
|
+
*
|
|
6
|
+
* 会话分组(今天/昨天/更早)+ 选中高亮 + 搜索过滤 + 重命名/删除/新建。
|
|
7
|
+
* 手动优先(let + render()):
|
|
8
|
+
* - 重命名:行内编辑按钮 → 输入框(预填原标题)→ Enter 确认 / Escape 取消
|
|
9
|
+
* - 删除:悬停行内删除按钮(裁剪:不做右键菜单)
|
|
10
|
+
* - 键盘:方向键移动焦点 + Enter 激活(列表容器 onKeyDown)
|
|
11
|
+
*
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <SessionList sessions={sessions} activeId={cur} onSelect={setCur}
|
|
14
|
+
* onNew={createSession} onRename={renameSession} onDelete={deleteSession} searchable />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export interface Session {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
/** 更新时间戳(ms)——分组(今天/昨天/更早);缺省进「更早」 */
|
|
21
|
+
updatedAt?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface SessionListProps {
|
|
24
|
+
sessions: Session[];
|
|
25
|
+
/** 当前选中会话 id(高亮 + aria-selected) */
|
|
26
|
+
activeId?: string;
|
|
27
|
+
/** 点击会话(键盘 Enter 同) */
|
|
28
|
+
onSelect?: (id: string) => void;
|
|
29
|
+
/** 新建按钮(渲染条件:onNew 提供) */
|
|
30
|
+
onNew?: () => void;
|
|
31
|
+
/** 重命名(行内编辑 Enter 确认) */
|
|
32
|
+
onRename?: (id: string, title: string) => void;
|
|
33
|
+
/** 删除(行内悬停按钮) */
|
|
34
|
+
onDelete?: (id: string) => void;
|
|
35
|
+
/** 顶部搜索框(按标题过滤) */
|
|
36
|
+
searchable?: boolean;
|
|
37
|
+
/** 新建按钮文案(默认「新建会话」) */
|
|
38
|
+
newLabel?: string;
|
|
39
|
+
}
|
|
40
|
+
/** 分组标签:今天 / 昨天 / 更早(确定性:now 可注入) */
|
|
41
|
+
export declare function groupKey(t: number, now?: number): 'today' | 'yesterday' | 'earlier';
|
|
42
|
+
export declare const SessionList: Component<SessionListProps, WfuiContext>;
|
|
@@ -25,7 +25,7 @@ export interface TourProps {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Tour — 新手引导(步骤式)。
|
|
28
|
-
*
|
|
28
|
+
* 统一 usePopup:mask 遮罩 + portal 出口;position 回调更新目标 rect(scroll 跟随)。
|
|
29
29
|
*
|
|
30
30
|
* 状态纪律:
|
|
31
31
|
* - 步骤索引闭包 let + render()(手动模式——避免 $ 内置类型问题)
|
|
@@ -16,8 +16,9 @@ export interface TreeSelectProps {
|
|
|
16
16
|
export declare function findLabel(nodes: TreeNode[], key: string): string | undefined;
|
|
17
17
|
/**
|
|
18
18
|
* TreeSelect — 树形选择(Tree + 下拉组合)。
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* 弹层经 ctx.ui.usePopup(§5.4 弹窗纪律统一组合器):portal 到 #__wf_portal +
|
|
20
|
+
* fixed 定位/视口夹紧 + 外部点击关闭 + Escape 关闭 + ref 稳定——不再手写
|
|
21
|
+
* usePopupPosition/createPortal/panelRef(此前缺外部点击关闭的真实 bug)。
|
|
21
22
|
* 单选 selectedKeys / 多选 checkable checkedKeys(父子联动)。
|
|
22
23
|
* 受控纪律:value 受控无 onChange → warn。
|
|
23
24
|
*/
|
|
@@ -13,8 +13,8 @@ export { Input } from './Input/Input.ts';
|
|
|
13
13
|
export type { InputProps } from './Input/Input.ts';
|
|
14
14
|
export { Textarea } from './Textarea/Textarea.ts';
|
|
15
15
|
export type { TextareaProps } from './Textarea/Textarea.ts';
|
|
16
|
-
export { Select } from './Select/Select.ts';
|
|
17
|
-
export type { SelectProps, SelectOption } from './Select/Select.ts';
|
|
16
|
+
export { Select, flattenOptions } from './Select/Select.ts';
|
|
17
|
+
export type { SelectProps, SelectOption, SelectOptionGroup, SelectOptions } from './Select/Select.ts';
|
|
18
18
|
export { Checkbox } from './Checkbox/Checkbox.ts';
|
|
19
19
|
export type { CheckboxProps } from './Checkbox/Checkbox.ts';
|
|
20
20
|
export { Switch } from './Switch/Switch.ts';
|
|
@@ -223,3 +223,11 @@ export { Scrollbar } from './Scrollbar/Scrollbar.ts';
|
|
|
223
223
|
export type { ScrollbarProps } from './Scrollbar/Scrollbar.ts';
|
|
224
224
|
export { AlertGroup } from './AlertGroup/AlertGroup.ts';
|
|
225
225
|
export type { AlertGroupProps, AlertGroupItem } from './AlertGroup/AlertGroup.ts';
|
|
226
|
+
export { JsonSchemaForm } from './JsonSchemaForm/JsonSchemaForm.ts';
|
|
227
|
+
export type { JsonSchemaFormProps, JsonSchema } from './JsonSchemaForm/JsonSchemaForm.ts';
|
|
228
|
+
export { ReasoningBlock } from './ReasoningBlock/ReasoningBlock.ts';
|
|
229
|
+
export type { ReasoningBlockProps } from './ReasoningBlock/ReasoningBlock.ts';
|
|
230
|
+
export { CitationCard } from './CitationCard/CitationCard.ts';
|
|
231
|
+
export type { CitationCardProps, Citation } from './CitationCard/CitationCard.ts';
|
|
232
|
+
export { SessionList, groupKey } from './SessionList/SessionList.ts';
|
|
233
|
+
export type { SessionListProps, Session } from './SessionList/SessionList.ts';
|