Skip to content

Commit d3a881b

Browse files
committed
feat: add new UI components and utilities
- Introduced a new Toaster component for notifications. - Added Spinner component for loading indicators. - Implemented Switch component for toggle functionality. - Created Table component with associated subcomponents (TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption). - Developed Tabs component with TabsList, TabsTrigger, and TabsContent. - Added Textarea component for multi-line text input. - Implemented ToggleGroup and Toggle components for grouped toggle functionality. - Created Tooltip component with TooltipProvider, TooltipTrigger, and TooltipContent. - Configured Tailwind CSS for styling and theming. - Set up TypeScript configuration for core and react packages. - Established a Registry class for component management in core package. - Defined SchemaNode and ComponentRendererProps types for schema-based rendering.
1 parent 6b10f78 commit d3a881b

178 files changed

Lines changed: 2951 additions & 3460 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/copilot-instructions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ Your biggest competitive advantage is Design System Compatibility.
3636
🧩 Rule #3: The "Schema First" Mindset
3737
All components are driven by the Schema in packages/types.
3838
* Documentation: Every property in the Schema MUST have JSDoc. This allows us to auto-generate documentation for the open-source community.
39+
📄 Rule #4: JSON-Object First (No Runtime YAML)
40+
While ObjectQL uses YAML for definition, **Object UI Runtime** expects **JavaScript Objects** (JSON).
41+
* **Constraint:** The `<SchemaRenderer schema={...} />` prop MUST be a typed Object, not a YAML string.
42+
* **Why:** To keep the core bundle small and fast. YAML parsing belongs in the **Backend API** or **Build Tools**.
3943
5. Implementation Patterns
4044
Pattern A: The Universal Data Adapter
4145
We support ObjectQL, but we also support generic REST.

RESTRUCTURE_PLAN.md

Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
# Object UI Packages 重构方案
2+
3+
## 当前问题分析
4+
5+
### 现有结构
6+
```
7+
packages/
8+
├── core/ # ❌ 仅有占位代码
9+
├── designer/ # ✅ 设计器(正确)
10+
├── engine/ # ❌ 仅有版本号占位
11+
├── protocol/ # ⚠️ 定义了 SchemaNode 但职责不清
12+
├── react/ # ❌ 仅有占位代码
13+
├── renderer/ # ⚠️ 实际承担了 SchemaRenderer 和所有渲染器
14+
└── ui/ # ⚠️ 包含了 Shadcn 组件和 metadata
15+
```
16+
17+
### 核心问题
18+
1. **职责混乱**: `renderer` 包同时承担了注册表、渲染器和组件映射
19+
2. **命名不符**: 没有 `components` 包,违反了 copilot-instructions 中的标准
20+
3. **空包存在**: `core``engine``react` 几乎没有实际内容
21+
4. **边界模糊**: `protocol` vs `core` vs `engine` 的分工不明确
22+
23+
---
24+
25+
## 标准架构(目标)
26+
27+
根据 `.github/copilot-instructions.md``docs/spec/` 定义的标准架构:
28+
29+
```
30+
packages/
31+
├── core/ # 🧠 The Brain - 纯 TypeScript 逻辑
32+
│ ├── types/ # Schema 类型定义(从 protocol 迁移)
33+
│ ├── registry/ # 组件注册表(从 renderer 迁移)
34+
│ ├── data-scope/ # 数据作用域链
35+
│ ├── evaluator/ # 表达式求值引擎
36+
│ └── validators/ # Zod 验证器
37+
38+
├── react/ # 🔌 The Glue - React 绑定层
39+
│ ├── SchemaRenderer.tsx # 主渲染器(从 renderer 迁移)
40+
│ ├── hooks/ # useRenderer, useDataScope
41+
│ └── context/ # React Context 包装器
42+
43+
├── components/ # 💪 The Body - 官方标准 UI 实现
44+
│ ├── ui/ # Shadcn 原子组件(从 ui 迁移)
45+
│ └── renderers/ # ObjectUI 包装器(从 renderer 迁移)
46+
│ ├── basic/ # 基础组件渲染器
47+
│ ├── form/ # 表单组件渲染器
48+
│ ├── layout/ # 布局组件渲染器
49+
│ └── ...
50+
51+
├── designer/ # 🎨 The Tool - 可视化编辑器(保持不变)
52+
53+
├── plugins/ # ⚔️ The Weapons - 重量级集成(新增)
54+
│ ├── ag-grid/ # AG Grid 集成
55+
│ ├── devexpress/ # DevExpress 集成
56+
│ └── monaco/ # Monaco 编辑器集成
57+
58+
└── [废弃包]
59+
├── protocol/ # ❌ 合并到 core/types
60+
├── engine/ # ❌ 合并到 core
61+
├── renderer/ # ❌ 拆分到 react + components
62+
└── ui/ # ❌ 重命名为 components/ui
63+
```
64+
65+
---
66+
67+
## 详细迁移路径
68+
69+
### Phase 1: 创建新的标准结构
70+
71+
#### 1.1 重构 `packages/core`
72+
73+
**目标**: 成为纯 TypeScript 的核心逻辑层,零 React 依赖
74+
75+
```
76+
packages/core/
77+
├── package.json # 依赖: zod, lodash (无 React)
78+
├── tsconfig.json
79+
└── src/
80+
├── index.ts
81+
├── types/
82+
│ ├── base.ts # BaseSchema interface
83+
│ ├── components.ts # 所有组件的 Schema 定义
84+
│ ├── page.ts # PageSchema
85+
│ ├── view.ts # ViewSchema
86+
│ └── object.ts # ObjectSchema
87+
88+
├── registry/
89+
│ ├── Registry.ts # 注册表核心逻辑
90+
│ └── ComponentConfig.ts # 组件配置类型
91+
92+
├── data-scope/
93+
│ ├── DataScope.ts # 作用域链实现
94+
│ └── ScopeChain.ts # 原型链查找
95+
96+
├── evaluator/
97+
│ ├── Evaluator.ts # 表达式求值
98+
│ └── ExpressionParser.ts # ${...} 解析器
99+
100+
└── validators/
101+
└── schemas.ts # Zod 验证规则
102+
```
103+
104+
**迁移清单**:
105+
- ✅ 从 `packages/protocol/src/index.ts` 迁移 `SchemaNode` 等类型
106+
- ✅ 从 `packages/renderer/src/registry.tsx` 迁移注册表逻辑
107+
- ✅ 新建 `DataScope``Evaluator` 实现
108+
109+
---
110+
111+
#### 1.2 重构 `packages/react`
112+
113+
**目标**: React 绑定层,连接 core 和 components
114+
115+
```
116+
packages/react/
117+
├── package.json # peerDeps: react, react-dom
118+
│ # deps: @object-ui/core
119+
├── tsconfig.json
120+
└── src/
121+
├── index.ts
122+
├── SchemaRenderer.tsx # 主渲染器(从 renderer 迁移)
123+
├── hooks/
124+
│ ├── useRenderer.ts
125+
│ ├── useDataScope.ts
126+
│ └── useRegistry.ts
127+
└── context/
128+
├── RendererContext.tsx
129+
└── DataScopeContext.tsx
130+
```
131+
132+
**迁移清单**:
133+
- ✅ 从 `packages/renderer/src/index.tsx` 迁移 `SchemaRenderer`
134+
- ✅ 创建 React Hooks 封装 core 逻辑
135+
136+
---
137+
138+
#### 1.3 创建 `packages/components`
139+
140+
**目标**: 官方标准组件库,包含 Shadcn UI + ObjectUI 渲染器
141+
142+
```
143+
packages/components/
144+
├── package.json
145+
│ # deps: @object-ui/core, @object-ui/react
146+
│ # deps: @radix-ui/*, tailwindcss, lucide-react
147+
├── components.json # Shadcn 配置(从 ui 迁移)
148+
├── tailwind.config.js
149+
└── src/
150+
├── index.ts # 统一导出
151+
├── index.css # Tailwind 基础样式
152+
153+
├── ui/ # 🟦 Shadcn 原子组件(从 packages/ui 迁移)
154+
│ ├── button.tsx
155+
│ ├── input.tsx
156+
│ ├── select.tsx
157+
│ └── ...
158+
159+
└── renderers/ # 🟨 ObjectUI 包装器(从 renderer 迁移)
160+
├── basic/
161+
│ ├── ButtonRenderer.tsx
162+
│ ├── TextRenderer.tsx
163+
│ └── index.ts
164+
├── form/
165+
│ ├── InputRenderer.tsx
166+
│ ├── SelectRenderer.tsx
167+
│ └── index.ts
168+
├── layout/
169+
│ ├── ContainerRenderer.tsx
170+
│ ├── GridRenderer.tsx
171+
│ └── index.ts
172+
├── data-display/
173+
│ ├── TableRenderer.tsx
174+
│ └── CardRenderer.tsx
175+
└── index.ts # 自动注册所有渲染器
176+
```
177+
178+
**迁移清单**:
179+
- ✅ 从 `packages/ui/src/components/ui/*` 迁移 Shadcn 组件
180+
- ✅ 从 `packages/renderer/src/renderers/*` 迁移渲染器
181+
- ✅ 保留 Tailwind 配置和样式
182+
183+
---
184+
185+
#### 1.4 创建 `packages/plugins/`
186+
187+
**目标**: 隔离重量级第三方集成
188+
189+
```
190+
packages/plugins/
191+
├── ag-grid/
192+
│ ├── package.json # deps: ag-grid-react
193+
│ └── src/
194+
│ ├── GridRenderer.tsx
195+
│ └── index.ts
196+
197+
├── devexpress/
198+
│ ├── package.json # deps: devextreme-react
199+
│ └── src/
200+
201+
└── monaco/
202+
├── package.json # deps: @monaco-editor/react
203+
└── src/
204+
```
205+
206+
---
207+
208+
### Phase 2: 更新依赖关系
209+
210+
#### 依赖链
211+
```
212+
designer
213+
214+
components ──→ react ──→ core
215+
↓ ↓
216+
plugins/* (peerDeps: react, react-dom)
217+
```
218+
219+
#### Package.json 依赖矩阵
220+
221+
| Package | Dependencies | Peer Dependencies |
222+
|--------------|-------------------------------------------|-------------------|
223+
| `core` | zod, lodash | - |
224+
| `react` | @object-ui/core | react, react-dom |
225+
| `components` | @object-ui/core, @object-ui/react, @radix-ui/*, tailwindcss | react, react-dom |
226+
| `designer` | @object-ui/components | react, react-dom |
227+
| `plugins/*` | @object-ui/components, <plugin-lib> | react, react-dom |
228+
229+
---
230+
231+
### Phase 3: 废弃旧包
232+
233+
```bash
234+
# 删除或归档
235+
packages/protocol/ → 合并到 core/types
236+
packages/engine/ → 合并到 core
237+
packages/renderer/ → 拆分到 react + components
238+
packages/ui/ → 重命名为 components/ui
239+
```
240+
241+
---
242+
243+
## 迁移步骤(执行顺序)
244+
245+
### Step 1: 准备阶段
246+
```bash
247+
# 1. 创建新的包结构
248+
mkdir -p packages/components/{src/{ui,renderers},metadata}
249+
mkdir -p packages/plugins/{ag-grid,devexpress,monaco}
250+
251+
# 2. 备份当前代码
252+
git checkout -b refactor/packages-restructure
253+
```
254+
255+
### Step 2: 迁移 Core(最底层)
256+
```bash
257+
# 从 protocol 迁移类型
258+
cp packages/protocol/src/* packages/core/src/types/
259+
260+
# 从 renderer 迁移注册表
261+
cp packages/renderer/src/registry.tsx packages/core/src/registry/Registry.ts
262+
# 🔧 移除 React 依赖,改为纯 TypeScript
263+
```
264+
265+
### Step 3: 迁移 React(中间层)
266+
```bash
267+
# 迁移 SchemaRenderer
268+
cp packages/renderer/src/index.tsx packages/react/src/SchemaRenderer.tsx
269+
# 🔧 更新 import 路径指向 @object-ui/core
270+
```
271+
272+
### Step 4: 迁移 Components(UI 层)
273+
```bash
274+
# 迁移 Shadcn UI 组件
275+
cp -r packages/ui/src/components/ui packages/components/src/ui
276+
cp packages/ui/src/index.css packages/components/src/
277+
278+
# 迁移渲染器
279+
cp -r packages/renderer/src/renderers packages/components/src/
280+
281+
# 迁移 metadata
282+
cp -r packages/ui/metadata packages/components/metadata
283+
```
284+
285+
### Step 5: 更新依赖
286+
```bash
287+
# 在所有包中更新 import 路径
288+
# 从: import { X } from '@object-ui/protocol'
289+
# 到: import { X } from '@object-ui/core'
290+
291+
# 从: import { SchemaRenderer } from '@object-ui/renderer'
292+
# 到: import { SchemaRenderer } from '@object-ui/react'
293+
```
294+
295+
### Step 6: 删除旧包
296+
```bash
297+
rm -rf packages/protocol
298+
rm -rf packages/engine
299+
rm -rf packages/renderer
300+
rm -rf packages/ui
301+
```
302+
303+
---
304+
305+
## 验证清单
306+
307+
### 功能验证
308+
- [ ] `examples/prototype` 能正常构建和运行
309+
- [ ] `examples/designer-demo` 能正常构建和运行
310+
- [ ] 所有单元测试通过
311+
- [ ] TypeScript 类型检查通过
312+
313+
### 架构验证
314+
- [ ] `packages/core` 无 React 依赖
315+
- [ ] `packages/react` 只依赖 core + React
316+
- [ ] `packages/components` 包含完整的 UI + 渲染器
317+
- [ ] 循环依赖检查通过
318+
319+
### 文档验证
320+
- [ ] 更新 `README.md`
321+
- [ ] 更新 `docs/guide/installation.md`
322+
- [ ] 更新 `docs/spec/project-structure.md`
323+
- [ ] 更新 `.github/copilot-instructions.md`(如需调整)
324+
325+
---
326+
327+
## 关键设计决策
328+
329+
### 为什么合并 protocol 到 core?
330+
- `protocol` 原本只有类型定义,职责过窄
331+
- 类型定义是核心逻辑的一部分,应该在 `core`
332+
- 避免过度拆分导致包数量膨胀
333+
334+
### 为什么拆分 renderer?
335+
- `renderer` 违反了单一职责原则,同时包含:
336+
- 注册表逻辑(应该在 core)
337+
- React 绑定(应该在 react)
338+
- UI 组件(应该在 components)
339+
- 拆分后各层职责清晰,符合标准架构
340+
341+
### 为什么重命名 ui 为 components?
342+
- `ui` 命名过于宽泛
343+
- `components` 明确表达「官方标准组件库」的定位
344+
- 与 copilot-instructions 中的术语一致
345+
346+
### 为什么新增 plugins?
347+
- 隔离重量级第三方库(AG Grid 200KB+)
348+
- 支持按需加载,避免污染核心包
349+
- 为未来扩展预留空间
350+
351+
---
352+
353+
## 风险评估
354+
355+
### 高风险项
356+
1. **Import 路径大规模变更** - 可能遗漏部分引用
357+
- 缓解: 使用 IDE 全局搜索替换 + TypeScript 检查
358+
359+
2. **循环依赖** - components 依赖 react,react 依赖 core
360+
- 缓解: 严格遵守单向依赖原则,禁止反向引用
361+
362+
### 中风险项
363+
1. **测试覆盖不足** - 当前测试较少,可能遗漏回归问题
364+
- 缓解: 重构前补充关键路径的集成测试
365+
366+
2. **第三方依赖版本冲突** - Shadcn 组件依赖特定 Radix 版本
367+
- 缓解: 使用 pnpm 的 workspace 协议锁定版本
368+
369+
---
370+
371+
## 成功标准
372+
373+
重构完成后应达到:
374+
375+
1.**架构清晰**: 每个包职责单一明确
376+
2.**零 React 污染**: core 包可以在 Node.js 中使用
377+
3.**Tree-shakable**: 用户只引入需要的组件
378+
4.**向后兼容**: 旧代码通过 import 路径调整即可迁移
379+
5.**文档完整**: AI 和人类都能快速理解架构
380+
381+
---
382+
383+
## 附录:参考文档
384+
385+
- [Architecture Blueprint](docs/spec/architecture.md)
386+
- [Project Structure Spec](docs/spec/project-structure.md)
387+
- [Copilot Instructions](.github/copilot-instructions.md)

0 commit comments

Comments
 (0)