create-blocklet 0.9.24 → 0.9.26
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/index.js +46 -5
- package/package.json +1 -1
- package/templates/component-studio/.cursor/rules/@metadata-json.mdc +549 -0
- package/templates/component-studio/.cursor/rules/component-studio.mdc +138 -0
- package/templates/component-studio/.cursor/rules/index-tsx.mdc +192 -0
- package/templates/component-studio/.init-component-studio +0 -0
- package/templates/component-studio/README.md +44 -0
- package/templates/component-studio/_theme.tsx +4 -0
- package/templates/component-studio/api/dev.ts +21 -0
- package/templates/component-studio/api/src/index.ts +50 -0
- package/templates/component-studio/api/src/libs/auth.ts +17 -0
- package/templates/component-studio/api/src/libs/env.ts +6 -0
- package/templates/component-studio/api/src/libs/logger.ts +3 -0
- package/templates/component-studio/api/src/routes/index.ts +12 -0
- package/templates/component-studio/api/third.d.ts +17 -0
- package/templates/component-studio/biome.json +53 -0
- package/templates/component-studio/blocklet.md +8 -0
- package/templates/component-studio/blocklet.yml +58 -0
- package/templates/component-studio/index.html +15 -0
- package/templates/component-studio/logo.png +0 -0
- package/templates/component-studio/package.json +117 -0
- package/templates/component-studio/scripts/build-clean.mjs +6 -0
- package/templates/component-studio/scripts/bump-version.mjs +39 -0
- package/templates/component-studio/scripts/init-component-studio.mjs +21 -0
- package/templates/component-studio/src/HelloWorld/@metadata.json +433 -0
- package/templates/component-studio/src/HelloWorld/index.tsx +560 -0
- package/templates/component-studio/template-info.json +12 -0
- package/templates/component-studio/tsconfig.api.json +12 -0
- package/templates/component-studio/tsconfig.json +102 -0
- package/templates/component-studio/vite-server.config.ts +20 -0
- package/templates/component-studio/vite.config.ts +28 -0
- package/templates/did-connect-dapp/package.json +1 -1
- package/templates/did-wallet-dapp/package.json +1 -1
- package/templates/react-aigne-dapp/package.json +1 -1
- package/templates/react-dapp/package.json +1 -1
- package/templates/react-dapp-ts/package.json +1 -1
- package/templates/react-gun-dapp/package.json +1 -1
- package/templates/react-static/package.json +1 -1
- package/templates/solidjs-dapp/package.json +1 -1
- package/templates/solidjs-static/package.json +1 -1
- package/templates/svelte-dapp/package.json +1 -1
- package/templates/svelte-static/package.json +1 -1
- package/templates/todo-list-example/package.json +1 -1
- package/templates/vue-dapp/package.json +1 -1
- package/templates/vue-static/package.json +1 -1
- package/templates/vue-ts-static/package.json +1 -1
- package/templates/vue2-dapp/package.json +1 -1
- package/templates/vue2-static/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
description:
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
# Component Studio 说明
|
|
7
|
+
|
|
8
|
+
## 概述
|
|
9
|
+
Component Studio 是一个强大的组件开发环境,让开发者能够创建、配置和管理可复用的组件。它通过声明式配置和实现分离的方式,实现了组件的高度可定制性和易用性。
|
|
10
|
+
|
|
11
|
+
## 工作原理
|
|
12
|
+
Component Studio 基于两个核心文件协同工作:
|
|
13
|
+
- `@metadata.json`:声明组件的元数据和可配置属性
|
|
14
|
+
- `index.tsx`:实现组件的渲染逻辑和交互行为
|
|
15
|
+
|
|
16
|
+
这种分离架构使得组件能够同时满足开发便捷性和使用灵活性的需求。
|
|
17
|
+
|
|
18
|
+
## 项目结构
|
|
19
|
+
|
|
20
|
+
项目需要遵循工程化思想,减少代码堆积
|
|
21
|
+
**重要提醒** 尤其是对于 EditComponent 可以抽离公用的配置逻辑,最后通过 JSON Schema 进行渲染
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
your-component-studio/
|
|
25
|
+
├── api/ # 后端API代码
|
|
26
|
+
│ ├── dev.ts # 开发服务器入口
|
|
27
|
+
│ ├── src/ # API源代码目录
|
|
28
|
+
│ └── third.d.ts # 三方库类型声明
|
|
29
|
+
├── scripts/ # 构建和版本管理脚本
|
|
30
|
+
│ ├── build-clean.mjs # 清理构建脚本
|
|
31
|
+
│ └── bump-version.mjs # 版本升级脚本
|
|
32
|
+
├── src/ # 前端源代码
|
|
33
|
+
│ ├── HelloWorld/ # 示例HelloWorld区块
|
|
34
|
+
│ │ └── index.tsx # 区块入口
|
|
35
|
+
│ │ └── @metadata.json # 区块元数据
|
|
36
|
+
│ │ └── @preview-images/ # 区块预览图目录
|
|
37
|
+
│ └── <your-component-name>/ # 你的区块目录
|
|
38
|
+
│ | └── index.tsx # 区块入口
|
|
39
|
+
│ | └── @metadata.json # 区块元数据
|
|
40
|
+
│ | └── @preview-images/ # 区块预览图目录
|
|
41
|
+
│ └── components/ # 组件目录
|
|
42
|
+
│ └── utils/ # 工具函数目录
|
|
43
|
+
│ └── types/ # 类型声明目录
|
|
44
|
+
├── package.json # 项目配置和依赖
|
|
45
|
+
├── vite.config.mts # Vite客户端配置
|
|
46
|
+
└── vite-server.config.ts # Vite服务端配置
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## 核心功能
|
|
51
|
+
|
|
52
|
+
### 组件定义与配置
|
|
53
|
+
- 通过 `@metadata.json` 定义组件的基本信息和属性
|
|
54
|
+
- 支持丰富的属性类型(文本、数值、颜色、对象等)
|
|
55
|
+
- 提供多语言支持和国际化能力
|
|
56
|
+
- 控制属性在编辑器中的显示方式
|
|
57
|
+
|
|
58
|
+
### 组件实现与渲染
|
|
59
|
+
- 在 `index.tsx` 中实现组件的具体行为
|
|
60
|
+
- 使用 React 函数组件和 TypeScript 类型系统
|
|
61
|
+
- 支持自定义编辑界面(EditComponent)
|
|
62
|
+
- 提供响应式和交互体验
|
|
63
|
+
|
|
64
|
+
## 开发注意事项
|
|
65
|
+
|
|
66
|
+
### 上下文与依赖管理
|
|
67
|
+
- **避免使用 React Context** - 组件可能在无特定上下文的环境中运行,依赖上下文会导致组件失效
|
|
68
|
+
- **谨慎选择第三方库** - 避免使用依赖于全局上下文或特定环境的第三方库
|
|
69
|
+
- **依赖最小化** - 组件应尽可能减少外部依赖,确保高度独立性
|
|
70
|
+
- **明确依赖声明** - 必要的依赖应在文档中明确说明,并在项目配置中正确引用
|
|
71
|
+
|
|
72
|
+
### 容错与健壮性
|
|
73
|
+
- **防御性编程** - 实现空值检查和类型验证,防止运行时错误
|
|
74
|
+
- **优雅降级** - 当属性缺失或格式错误时,组件应能优雅降级而非崩溃
|
|
75
|
+
- **边界情况处理** - 考虑并测试极端情况(空数据、超长文本、网络错误等)
|
|
76
|
+
- **错误边界** - 使用 React 错误边界捕获渲染错误,避免整个应用崩溃
|
|
77
|
+
|
|
78
|
+
### 工程化与复用
|
|
79
|
+
- **组件封装** - 确保组件功能内聚,接口清晰,方便在不同项目中复用
|
|
80
|
+
- **版本控制** - 使用语义化版本管理组件更新
|
|
81
|
+
- **文档完善** - 提供详细的使用文档和示例,降低使用门槛
|
|
82
|
+
- **测试覆盖** - 编写单元测试和集成测试,确保组件质量
|
|
83
|
+
- **构建优化** - 配置合适的构建流程,减小打包体积
|
|
84
|
+
|
|
85
|
+
## 设计与用户体验要求
|
|
86
|
+
|
|
87
|
+
### 视觉设计原则
|
|
88
|
+
- **美观性** - 组件应具有现代、专业的外观,符合当代设计趋势
|
|
89
|
+
- **一致性** - 组件样式应与整体设计系统保持一致
|
|
90
|
+
- **层次感** - 使用适当的阴影、间距和颜色创造视觉层次
|
|
91
|
+
- **动效适度** - 添加适当的过渡动画,提升用户体验,但避免过度装饰
|
|
92
|
+
|
|
93
|
+
### 用户体验标准
|
|
94
|
+
- **响应灵敏** - 组件应对用户操作提供即时反馈
|
|
95
|
+
- **容错设计** - 妥善处理各种边缘情况和错误状态
|
|
96
|
+
- **直观操作** - 用户无需额外说明即可理解如何使用组件
|
|
97
|
+
- **可访问性** - 符合WCAG 2.1标准,支持键盘导航和屏幕阅读器
|
|
98
|
+
|
|
99
|
+
### 性能要求
|
|
100
|
+
- 组件初始渲染时间应控制在300ms以内
|
|
101
|
+
- 交互响应延迟不应超过100ms
|
|
102
|
+
- 优化重渲染逻辑,避免不必要的DOM更新
|
|
103
|
+
- 大型组件应考虑代码分割和懒加载策略
|
|
104
|
+
|
|
105
|
+
## 文件关系详解
|
|
106
|
+
|
|
107
|
+
### @metadata.json 与 index.tsx 的映射关系
|
|
108
|
+
- `@metadata.json` 中的 `properties.[id].data.key` 对应 `index.tsx` 中 BlockProps 的属性名
|
|
109
|
+
- `@metadata.json` 中的属性类型转换为 TypeScript 类型定义
|
|
110
|
+
- `@metadata.json` 中的默认值在 `index.tsx` 中作为组件默认参数
|
|
111
|
+
- `@metadata.json` 中的嵌套属性(subProperties)在 `index.tsx` 中体现为嵌套接口
|
|
112
|
+
|
|
113
|
+
### 文件依赖与更新
|
|
114
|
+
1. 修改 `@metadata.json` 后需同步更新 `index.tsx` 中的类型定义
|
|
115
|
+
2. 在 `index.tsx` 中添加新功能时,可能需要在 `@metadata.json` 中添加相应配置
|
|
116
|
+
3. 两个文件的同步性对组件的正常运行至关重要
|
|
117
|
+
|
|
118
|
+
## 组件开发流程
|
|
119
|
+
1. 在 `@metadata.json` 中定义组件属性和元数据
|
|
120
|
+
2. 在 `index.tsx` 中实现组件的 BlockProps 接口
|
|
121
|
+
3. 编写组件的渲染逻辑和行为
|
|
122
|
+
4. 进行视觉设计和用户体验优化
|
|
123
|
+
5. 可选:实现 EditComponent 提供自定义编辑体验
|
|
124
|
+
6. 测试组件在不同配置和设备下的表现
|
|
125
|
+
|
|
126
|
+
## 最佳实践
|
|
127
|
+
- 保持 `@metadata.json` 和 `index.tsx` 的同步更新
|
|
128
|
+
- 遵循 TypeScript 和 React 的最佳实践
|
|
129
|
+
- 使用语义化的属性命名
|
|
130
|
+
- 为组件提供合理的默认值
|
|
131
|
+
- 优先考虑移动端体验,实现响应式设计
|
|
132
|
+
- 通过用户测试验证组件的可用性
|
|
133
|
+
- 使用CSS变量实现主题定制能力
|
|
134
|
+
|
|
135
|
+
## 补充资源
|
|
136
|
+
组件开发中可参考同目录下 2 个规则
|
|
137
|
+
- `@metadat-json.mdc`
|
|
138
|
+
- `index-tsx.mdc`
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
description:
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
# index.tsx 文件说明
|
|
7
|
+
|
|
8
|
+
## 概述
|
|
9
|
+
`index.tsx` 是 Component Studio 中组件的实现文件,负责组件的渲染逻辑和交互行为。它与 `@metadata.json` 紧密配合,共同定义了一个完整的可配置组件。
|
|
10
|
+
|
|
11
|
+
## 工作原理
|
|
12
|
+
`index.tsx` 与 `@metadata.json` 通过属性映射相互关联:
|
|
13
|
+
- `@metadata.json` 定义组件的可配置属性及其元数据
|
|
14
|
+
- `index.tsx` 使用这些属性进行组件渲染和行为控制
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 关键部分
|
|
18
|
+
|
|
19
|
+
### BlockProps 接口
|
|
20
|
+
```typescript
|
|
21
|
+
export interface BlockProps {
|
|
22
|
+
/** @description id: gs1rn5jmxfvpxptx | type: string | visible: true */
|
|
23
|
+
title?: string;
|
|
24
|
+
/** @description id: 9ajrz12ik7esfk1z | type: string | visible: true */
|
|
25
|
+
description?: string;
|
|
26
|
+
// ...其他属性
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
这个接口定义了组件的属性类型,每个属性的注释包含:
|
|
31
|
+
- id 对应的 `@metadata.json` 中的 id
|
|
32
|
+
- key 属性类型
|
|
33
|
+
- visible 可见性
|
|
34
|
+
- 需要保持 `@description` 符号,这是 jsdom 在 ts 类型处理的时候,会被解析到 zod 上 `z.xxx().describe()`
|
|
35
|
+
|
|
36
|
+
#### BlockProps 最佳实践
|
|
37
|
+
- 所有属性默认应设为可选(使用 `?` 标记),以避免类型错误
|
|
38
|
+
- 保持注释格式的统一性,不要删除或修改 `@description` 内容
|
|
39
|
+
- 为复杂类型(如嵌套对象)定义独立的接口或类型,增强代码可读性
|
|
40
|
+
- 当添加新属性时,确保同步添加对应的注释,包含完整的 metadata 信息
|
|
41
|
+
- 使用语义化的属性名称,与 `@metadata.json` 中的 `key` 保持一致
|
|
42
|
+
|
|
43
|
+
### 组件实现
|
|
44
|
+
```typescript
|
|
45
|
+
export default function BlockComponent({
|
|
46
|
+
title = 'Hello World',
|
|
47
|
+
logo,
|
|
48
|
+
description,
|
|
49
|
+
// ...其他属性和默认值
|
|
50
|
+
}: BlockProps) {
|
|
51
|
+
// 组件实现逻辑
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
组件函数接收 `BlockProps` 定义的属性,并设置与 `@metadata.json` 中匹配的默认值。
|
|
56
|
+
|
|
57
|
+
#### 组件实现最佳实践
|
|
58
|
+
- 为常用属性设置默认值,确保组件在无参数时也能正常渲染
|
|
59
|
+
- 默认值应与 `@metadata.json` 中的 `defaultValue` 保持一致
|
|
60
|
+
- 使用解构赋值接收属性,简化代码结构
|
|
61
|
+
- 对于复杂的逻辑处理,考虑使用 React hooks 拆分功能
|
|
62
|
+
- 实现响应式设计,确保组件在不同尺寸下都能正常显示
|
|
63
|
+
- 添加适当的类型守卫检查复杂属性,防止运行时错误
|
|
64
|
+
- 考虑性能优化,避免不必要的重渲染(如使用 useMemo, useCallback)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### EditComponent
|
|
68
|
+
```typescript
|
|
69
|
+
export const EditComponent: React.FC<BlockProps & { onChange?: (value: BlockProps) => void }> = ({
|
|
70
|
+
onChange,
|
|
71
|
+
...props
|
|
72
|
+
}) => {
|
|
73
|
+
// 自定义编辑界面实现
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
这是组件的特殊编辑接口,提供了编辑器中的自定义控件,增强属性编辑体验。
|
|
78
|
+
|
|
79
|
+
#### EditComponent 最佳实践
|
|
80
|
+
- 当在 EditComponent 中为某个属性提供自定义控件时,应在 `@metadata.json` 中将该属性的 `visible` 设置为 `false`
|
|
81
|
+
- 使用 onChange 回调时确保传递完整的 props 对象,避免丢失其他属性值
|
|
82
|
+
- 为复杂编辑界面提供直观的 UI 分组和标签
|
|
83
|
+
- 考虑添加表单验证,确保用户输入的值有效
|
|
84
|
+
- 提供即时反馈,让用户知道其操作已被接收
|
|
85
|
+
- 保持编辑控件的样式与 Component Studio 整体风格一致
|
|
86
|
+
- 并不是所有的 Component 都需要这个自定义空间,尤其是 `type: 'url' | ‘yml’` 情况下,不建议替换
|
|
87
|
+
|
|
88
|
+
### 样式
|
|
89
|
+
组件样式在 Component Studio 中通常通过内联样式对象实现,便于与属性值动态绑定。
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// 样式对象分离示例
|
|
93
|
+
const cardStyle = {
|
|
94
|
+
padding: '1.5rem',
|
|
95
|
+
borderRadius: '12px',
|
|
96
|
+
background: 'rgba(255, 255, 255, 0.7)',
|
|
97
|
+
boxShadow: '0 10px 30px rgba(0, 0, 0, 0.08)'
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return <div style={cardStyle}>...</div>;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### 样式最佳实践
|
|
104
|
+
- **内联样式优先** - 使用内联样式(style对象)便于属性动态控制
|
|
105
|
+
- **样式对象分离** - 对于复杂组件,将样式对象提取到组件函数外,提高可读性
|
|
106
|
+
- **动态样式函数** - 创建函数生成依赖于属性的样式
|
|
107
|
+
```typescript
|
|
108
|
+
const getTitleStyle = (color) => ({
|
|
109
|
+
color,
|
|
110
|
+
fontSize: '1.5rem',
|
|
111
|
+
fontWeight: 600
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
- **响应式设计** - 使用条件样式或媒体查询实现适配不同设备
|
|
115
|
+
- **过渡动画** - 添加 transition 属性提升用户体验
|
|
116
|
+
- **交互增强** - 为互动元素添加悬停状态
|
|
117
|
+
- **性能优化** - 使用 useMemo 缓存样式对象,避免不必要的重新计算
|
|
118
|
+
```typescript
|
|
119
|
+
const buttonStyle = useMemo(() => ({
|
|
120
|
+
background: isActive ? activeColor : inactiveColor
|
|
121
|
+
}), [isActive, activeColor, inactiveColor]);
|
|
122
|
+
```
|
|
123
|
+
- **避免硬编码** - 使用属性传入的样式值,避免硬编码颜色等固定值
|
|
124
|
+
- **主题变量** - 考虑使用 CSS 变量实现主题定制
|
|
125
|
+
- **使用语义化命名** - 如 containerStyle, headerStyle 等增强可读性
|
|
126
|
+
|
|
127
|
+
## 与 @metadata.json 的关系
|
|
128
|
+
|
|
129
|
+
### 属性映射
|
|
130
|
+
每个在 `@metadata.json` 中定义的属性,在 `index.tsx` 中都有对应映射:
|
|
131
|
+
|
|
132
|
+
| @metadata.json | index.tsx |
|
|
133
|
+
|----------------|------------|
|
|
134
|
+
| `properties.[id].data.key` | BlockProps 中的属性名 |
|
|
135
|
+
| `properties.[id].data.type` | TypeScript 类型定义 |
|
|
136
|
+
| `properties.[id].data.locales.[lang].defaultValue` | 组件中的默认值 |
|
|
137
|
+
|
|
138
|
+
### 类型对应关系
|
|
139
|
+
- `string` → `string`
|
|
140
|
+
- `number` → `number`
|
|
141
|
+
- `boolean` → `boolean`
|
|
142
|
+
- `url` → 自定义对象类型
|
|
143
|
+
- `json` → 自定义对象类型
|
|
144
|
+
- `array` → 数组类型
|
|
145
|
+
- `component` → `any` 或特定组件类型
|
|
146
|
+
|
|
147
|
+
### 嵌套属性处理
|
|
148
|
+
`@metadata.json` 中的 `subProperties` 在 `index.tsx` 中通过嵌套接口定义映射:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
json?: {
|
|
152
|
+
/** @description id: gpy89bsxc6ovvlsp | type: string | visible: true */
|
|
153
|
+
foo?: string;
|
|
154
|
+
/** @description id: 1j34jdhdptp2xm5e | type: string | visible: true */
|
|
155
|
+
bar?: string;
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 通用最佳实践
|
|
160
|
+
以下是适用于整个组件开发过程的通用最佳实践:
|
|
161
|
+
|
|
162
|
+
1. **文件同步** - 修改 `@metadata.json` 或 `index.tsx` 时,确保两者保持同步
|
|
163
|
+
2. **版本控制** - 为重要更改添加清晰的注释和版本标记
|
|
164
|
+
3. **组件设计** - 遵循单一职责原则,每个组件只做一件事
|
|
165
|
+
4. **性能考虑** - 针对大型组件或频繁更新的场景进行性能优化
|
|
166
|
+
5. **可维护性** - 使用清晰的命名和注释,便于团队成员理解
|
|
167
|
+
|
|
168
|
+
## 编辑组件示例
|
|
169
|
+
对于需要特殊编辑体验的属性,可以通过 `EditComponent` 提供自定义编辑界面:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
export const EditComponent: React.FC<BlockProps & { onChange?: (value: BlockProps) => void }> = ({
|
|
173
|
+
onChange,
|
|
174
|
+
...props
|
|
175
|
+
}) => {
|
|
176
|
+
return (
|
|
177
|
+
<div>
|
|
178
|
+
<label>自定义编辑器</label>
|
|
179
|
+
<input
|
|
180
|
+
value={props.someProperty || ''}
|
|
181
|
+
onChange={(e) => onChange?.({...props, someProperty: e.target.value})}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 组件属性如何生效
|
|
189
|
+
1. 用户在编辑器中配置属性值
|
|
190
|
+
2. 值存储到 `@metadata.json` 对应属性的 `defaultValue`
|
|
191
|
+
3. 运行时,这些值作为 props 传递给 `index.tsx` 中的组件
|
|
192
|
+
4. 组件根据接收到的 props 和默认值渲染界面
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
## PROJECT_DESCRIPTION
|
|
2
|
+
|
|
3
|
+
Component Studio is a development tool for creating Pages Kit visual blocks. With this tool, developers can:
|
|
4
|
+
|
|
5
|
+
- Create and manage reusable frontend block components
|
|
6
|
+
- Provide a visual editing interface for easy block configuration and preview
|
|
7
|
+
- Support development of various visualization component types (charts, forms, animations, etc.)
|
|
8
|
+
- Seamlessly integrate into the ArcBlock Blocklet ecosystem
|
|
9
|
+
|
|
10
|
+
## FILE_STRUCTURE
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
your-component-studio/
|
|
14
|
+
├── api/ # Backend API code
|
|
15
|
+
│ ├── dev.ts # Development server entry
|
|
16
|
+
│ ├── src/ # API source code directory
|
|
17
|
+
│ └── third.d.ts # Third-party library type declarations
|
|
18
|
+
├── scripts/ # Build and version management scripts
|
|
19
|
+
│ ├── build-clean.mjs # Build cleanup script
|
|
20
|
+
│ └── bump-version.mjs # Version upgrade script
|
|
21
|
+
├── src/ # Frontend source code
|
|
22
|
+
│ ├── HelloWorld/ # Example HelloWorld block
|
|
23
|
+
│ │ └── index.tsx # Block entry
|
|
24
|
+
│ │ └── @metadata.json # Block metadata
|
|
25
|
+
│ │ └── @preview-images/ # Block preview images directory
|
|
26
|
+
│ └── <your-component-name>/ # Your block directory
|
|
27
|
+
│ | └── index.tsx # Block entry
|
|
28
|
+
│ | └── @metadata.json # Block metadata
|
|
29
|
+
│ | └── @preview-images/ # Block preview images directory
|
|
30
|
+
│ └── components/ # Components directory
|
|
31
|
+
│ └── utils/ # Utility functions directory
|
|
32
|
+
│ └── types/ # Type declarations directory
|
|
33
|
+
├── package.json # Project configuration and dependencies
|
|
34
|
+
├── vite.config.mts # Vite client configuration
|
|
35
|
+
└── vite-server.config.ts # Vite server configuration
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## DEVELOPMENT
|
|
39
|
+
|
|
40
|
+
1. Use `pnpm run dev` to start the development environment, click the URL in the `Terminal` to access the Component Studio interface
|
|
41
|
+
2. Create new blocks by clicking the `+` button (alternatively, you can create new block components directly in the `src/` directory)
|
|
42
|
+
3. Develop block components and use `pnpm run build-lib` to build publishable blocks
|
|
43
|
+
4. Create a Resource Blocklet by clicking the `Create Resource` button, and publish it to the Blocklet Store
|
|
44
|
+
5. Install the Resource Blocklet in Pages Kit and use it in your pages
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { setupClient } from 'vite-plugin-blocklet';
|
|
4
|
+
|
|
5
|
+
import { app, server } from './src';
|
|
6
|
+
|
|
7
|
+
(async () => {
|
|
8
|
+
const viteDevServer = await setupClient(app, {
|
|
9
|
+
appType: 'custom',
|
|
10
|
+
server,
|
|
11
|
+
importMetaHot: import.meta.hot,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const html = readFileSync(path.join(__dirname, '../index.html'), 'utf-8');
|
|
15
|
+
const transformedHtml = await viteDevServer.transformIndexHtml('/', html);
|
|
16
|
+
|
|
17
|
+
// Add route to serve the transformed HTML
|
|
18
|
+
app.get('*', (req, res) => {
|
|
19
|
+
res.send(transformedHtml);
|
|
20
|
+
});
|
|
21
|
+
})();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import 'express-async-errors';
|
|
2
|
+
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
import cookieParser from 'cookie-parser';
|
|
6
|
+
import cors from 'cors';
|
|
7
|
+
import dotenv from 'dotenv-flow';
|
|
8
|
+
import express, { ErrorRequestHandler } from 'express';
|
|
9
|
+
import fallback from '@blocklet/sdk/lib/middlewares/fallback';
|
|
10
|
+
|
|
11
|
+
import logger from './libs/logger';
|
|
12
|
+
import routes from './routes';
|
|
13
|
+
|
|
14
|
+
dotenv.config();
|
|
15
|
+
|
|
16
|
+
const { name, version } = require('../../package.json');
|
|
17
|
+
|
|
18
|
+
export const app = express();
|
|
19
|
+
|
|
20
|
+
app.set('trust proxy', true);
|
|
21
|
+
app.use(cookieParser());
|
|
22
|
+
app.use(express.json({ limit: '1 mb' }));
|
|
23
|
+
app.use(express.urlencoded({ extended: true, limit: '1 mb' }));
|
|
24
|
+
app.use(cors());
|
|
25
|
+
|
|
26
|
+
const router = express.Router();
|
|
27
|
+
router.use(routes);
|
|
28
|
+
|
|
29
|
+
app.use(router);
|
|
30
|
+
|
|
31
|
+
const isProduction = process.env.NODE_ENV === 'production' || process.env.ABT_NODE_SERVICE_ENV === 'production';
|
|
32
|
+
|
|
33
|
+
if (isProduction) {
|
|
34
|
+
const staticDir = path.resolve(process.env.BLOCKLET_APP_DIR!, 'dist');
|
|
35
|
+
app.use(express.static(staticDir, { maxAge: '30d', index: false }));
|
|
36
|
+
app.use(fallback('index.html', { root: staticDir }));
|
|
37
|
+
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
+
app.use(<ErrorRequestHandler>((err, _req, res, _next) => {
|
|
40
|
+
logger.error(err.stack);
|
|
41
|
+
res.status(500).send('Something broke!');
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const port = parseInt(process.env.BLOCKLET_PORT!, 10);
|
|
46
|
+
|
|
47
|
+
export const server = app.listen(port, (err?: any) => {
|
|
48
|
+
if (err) throw err;
|
|
49
|
+
logger.info(`> ${name} v${version} ready on ${port}`);
|
|
50
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import AuthStorage from '@arcblock/did-auth-storage-nedb';
|
|
4
|
+
import getWallet from '@blocklet/sdk/lib/wallet';
|
|
5
|
+
import WalletAuthenticator from '@blocklet/sdk/lib/wallet-authenticator';
|
|
6
|
+
import WalletHandler from '@blocklet/sdk/lib/wallet-handler';
|
|
7
|
+
|
|
8
|
+
import env from './env';
|
|
9
|
+
|
|
10
|
+
export const wallet = getWallet();
|
|
11
|
+
export const authenticator = new WalletAuthenticator();
|
|
12
|
+
export const handlers = new WalletHandler({
|
|
13
|
+
authenticator,
|
|
14
|
+
tokenStorage: new AuthStorage({
|
|
15
|
+
dbPath: path.join(env.dataDir, 'auth.db'),
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { initBlockStudioRouter } from '@blocklet/pages-kit-block-studio/init-block-studio-router';
|
|
2
|
+
import { initResourceRouter } from '@blocklet/pages-kit-block-studio/init-resource-router';
|
|
3
|
+
import { initUploaderRouter } from '@blocklet/pages-kit-block-studio/init-uploader-router';
|
|
4
|
+
import { Router } from 'express';
|
|
5
|
+
|
|
6
|
+
const router = Router();
|
|
7
|
+
|
|
8
|
+
router.use('/api/resources', initResourceRouter);
|
|
9
|
+
router.use('/api/blocks', initBlockStudioRouter);
|
|
10
|
+
router.use(initUploaderRouter);
|
|
11
|
+
|
|
12
|
+
export default router;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare module 'vite-plugin-blocklet';
|
|
2
|
+
|
|
3
|
+
declare module 'express-history-api-fallback';
|
|
4
|
+
|
|
5
|
+
declare module 'express-async-errors';
|
|
6
|
+
|
|
7
|
+
declare namespace Express {
|
|
8
|
+
interface Request {
|
|
9
|
+
user?: {
|
|
10
|
+
did: string;
|
|
11
|
+
role: string;
|
|
12
|
+
fullName: string;
|
|
13
|
+
provider: string;
|
|
14
|
+
walletOS: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.5.3/schema.json",
|
|
3
|
+
"organizeImports": {
|
|
4
|
+
"enabled": true
|
|
5
|
+
},
|
|
6
|
+
"linter": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"rules": {
|
|
9
|
+
"recommended": true,
|
|
10
|
+
"correctness": {
|
|
11
|
+
"noUnusedVariables": "error"
|
|
12
|
+
},
|
|
13
|
+
"suspicious": {
|
|
14
|
+
"noExplicitAny": "warn"
|
|
15
|
+
},
|
|
16
|
+
"style": {
|
|
17
|
+
"noNonNullAssertion": "off",
|
|
18
|
+
"useShorthandArrayType": "error"
|
|
19
|
+
},
|
|
20
|
+
"a11y": {
|
|
21
|
+
"noNoninteractiveElementToInteractiveRole": "off",
|
|
22
|
+
"useKeyWithClickEvents": "off",
|
|
23
|
+
"useValidAnchor": "off",
|
|
24
|
+
"noSvgWithoutTitle": "off",
|
|
25
|
+
"useMouseEvents": "off"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"ignore": ["**/node_modules/**", "*.md"]
|
|
29
|
+
},
|
|
30
|
+
"formatter": {
|
|
31
|
+
"enabled": true,
|
|
32
|
+
"indentStyle": "space",
|
|
33
|
+
"indentWidth": 2,
|
|
34
|
+
"lineWidth": 100,
|
|
35
|
+
"include": ["**/*.{js,jsx,ts,tsx,json,css,less,scss,graphql}"]
|
|
36
|
+
},
|
|
37
|
+
"javascript": {
|
|
38
|
+
"formatter": {
|
|
39
|
+
"quoteStyle": "single",
|
|
40
|
+
"trailingComma": "es5",
|
|
41
|
+
"semicolons": "always"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"json": {
|
|
45
|
+
"parser": {
|
|
46
|
+
"allowComments": true,
|
|
47
|
+
"allowTrailingCommas": true
|
|
48
|
+
},
|
|
49
|
+
"formatter": {
|
|
50
|
+
"enabled": true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Component Studio
|
|
2
|
+
|
|
3
|
+
Component Studio is a development tool for creating Pages Kit visual blocks. With this tool, developers can:
|
|
4
|
+
|
|
5
|
+
- Create and manage reusable frontend block components
|
|
6
|
+
- Provide a visual editing interface for easy block configuration and preview
|
|
7
|
+
- Support development of various visualization component types (charts, forms, animations, etc.)
|
|
8
|
+
- Seamlessly integrate into the ArcBlock Blocklet ecosystem
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
title: Blocklet Template React
|
|
2
|
+
description: A Blocklet DAPP blocklet
|
|
3
|
+
keywords:
|
|
4
|
+
- blocklet
|
|
5
|
+
- react
|
|
6
|
+
group: dapp
|
|
7
|
+
did: ''
|
|
8
|
+
main: api/dist/index.js
|
|
9
|
+
author:
|
|
10
|
+
name: Blocklet
|
|
11
|
+
email: blocklet@arcblock.io
|
|
12
|
+
repository:
|
|
13
|
+
type: git
|
|
14
|
+
url: 'git+https://github.com/blocklet/create-blocklet.git'
|
|
15
|
+
specVersion: 1.2.8
|
|
16
|
+
version: 0.1.0
|
|
17
|
+
logo: logo.png
|
|
18
|
+
files:
|
|
19
|
+
- dist
|
|
20
|
+
- logo.png
|
|
21
|
+
- screenshots
|
|
22
|
+
interfaces:
|
|
23
|
+
- type: web
|
|
24
|
+
name: publicUrl
|
|
25
|
+
path: /
|
|
26
|
+
prefix: '*'
|
|
27
|
+
port: BLOCKLET_PORT
|
|
28
|
+
protocol: http
|
|
29
|
+
community: ''
|
|
30
|
+
documentation: ''
|
|
31
|
+
homepage: ''
|
|
32
|
+
license: ''
|
|
33
|
+
payment:
|
|
34
|
+
price: []
|
|
35
|
+
share: []
|
|
36
|
+
timeout:
|
|
37
|
+
start: 60
|
|
38
|
+
requirements:
|
|
39
|
+
server: '>=1.16.28'
|
|
40
|
+
os: '*'
|
|
41
|
+
cpu: '*'
|
|
42
|
+
scripts:
|
|
43
|
+
dev: npm run start
|
|
44
|
+
environments: []
|
|
45
|
+
capabilities: {}
|
|
46
|
+
screenshots: []
|
|
47
|
+
components:
|
|
48
|
+
- name: image-bin
|
|
49
|
+
required: true
|
|
50
|
+
mountPoint: /image-bin
|
|
51
|
+
source:
|
|
52
|
+
name: image-bin
|
|
53
|
+
version: latest
|
|
54
|
+
resource:
|
|
55
|
+
exportApi: /api/resources
|
|
56
|
+
types:
|
|
57
|
+
- type: page
|
|
58
|
+
description: Used by Pages Kit to import one or multiple components
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" href="/favicon.ico?imageFilter=convert&f=png&w=32" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<meta name="theme-color" content="#4F6AF5" />
|
|
8
|
+
</head>
|
|
9
|
+
|
|
10
|
+
<body>
|
|
11
|
+
<noscript> You need to enable JavaScript to run this app. </noscript>
|
|
12
|
+
<div id="root"></div>
|
|
13
|
+
<script type="module" src="/@pages-infra/main.js"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
Binary file
|