-
+
`,
styles: [
`
@@ -58,6 +61,7 @@ const content = JSON.stringify({
]
})
export class GenuiExample {
+ activeMaterials = materials;
generating = false;
requiredCompleteFieldSelectors = [
'[componentName=Text] > props > text',
diff --git a/docs/demos/angular/renderer/state.ts b/docs/demos/angular/renderer/state.ts
index 598e2582..69d352ce 100644
--- a/docs/demos/angular/renderer/state.ts
+++ b/docs/demos/angular/renderer/state.ts
@@ -1,13 +1,17 @@
import { Component } from '@angular/core';
-import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { GenuiConfigProvider, GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { materials } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/materials';
@Component({
- imports: [GenuiRenderer],
+ imports: [GenuiConfigProvider, GenuiRenderer],
template: `
-
+
+
+
`,
})
export class GenuiExample {
+ activeMaterials = materials;
schemaContent = {
componentName: 'Page',
state: {
diff --git a/docs/demos/chat/custom-actions.vue b/docs/demos/chat/custom-actions.vue
index 0883bada..16a4a739 100644
--- a/docs/demos/chat/custom-actions.vue
+++ b/docs/demos/chat/custom-actions.vue
@@ -1,9 +1,12 @@
-
+
+
+
diff --git a/docs/demos/en/angular/renderer/required-complete-field-selectors.vue b/docs/demos/en/angular/renderer/required-complete-field-selectors.vue
new file mode 100644
index 00000000..7412a67e
--- /dev/null
+++ b/docs/demos/en/angular/renderer/required-complete-field-selectors.vue
@@ -0,0 +1,79 @@
+
+ Start Rendering
+
+
+
Default buffered fields
+
+
+
+
Custom buffered fields: intercept text content
+
+
+
+
+
+
+
diff --git a/docs/demos/en/angular/renderer/state.vue b/docs/demos/en/angular/renderer/state.vue
new file mode 100644
index 00000000..8b908ef9
--- /dev/null
+++ b/docs/demos/en/angular/renderer/state.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
diff --git a/docs/demos/en/chat/components/assistant-footer.vue b/docs/demos/en/chat/components/assistant-footer.vue
new file mode 100644
index 00000000..3bf44f13
--- /dev/null
+++ b/docs/demos/en/chat/components/assistant-footer.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/components/user-footer.vue b/docs/demos/en/chat/components/user-footer.vue
new file mode 100644
index 00000000..d36faa39
--- /dev/null
+++ b/docs/demos/en/chat/components/user-footer.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/custom-actions.vue b/docs/demos/en/chat/custom-actions.vue
new file mode 100644
index 00000000..f2be34f4
--- /dev/null
+++ b/docs/demos/en/chat/custom-actions.vue
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/custom-components.vue b/docs/demos/en/chat/custom-components.vue
new file mode 100644
index 00000000..c35769d3
--- /dev/null
+++ b/docs/demos/en/chat/custom-components.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/custom-examples.vue b/docs/demos/en/chat/custom-examples.vue
new file mode 100644
index 00000000..ca22bd16
--- /dev/null
+++ b/docs/demos/en/chat/custom-examples.vue
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/custom-fetch.vue b/docs/demos/en/chat/custom-fetch.vue
new file mode 100644
index 00000000..c2d0cce9
--- /dev/null
+++ b/docs/demos/en/chat/custom-fetch.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/custom-snippets.vue b/docs/demos/en/chat/custom-snippets.vue
new file mode 100644
index 00000000..91449b74
--- /dev/null
+++ b/docs/demos/en/chat/custom-snippets.vue
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/footer-toolbar.vue b/docs/demos/en/chat/footer-toolbar.vue
new file mode 100644
index 00000000..d6f4bacc
--- /dev/null
+++ b/docs/demos/en/chat/footer-toolbar.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/history.vue b/docs/demos/en/chat/history.vue
new file mode 100644
index 00000000..dab2e4b2
--- /dev/null
+++ b/docs/demos/en/chat/history.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/demos/en/chat/image-upload.vue b/docs/demos/en/chat/image-upload.vue
new file mode 100644
index 00000000..47bcd070
--- /dev/null
+++ b/docs/demos/en/chat/image-upload.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/demos/en/config-provider/custom-theme.vue b/docs/demos/en/config-provider/custom-theme.vue
new file mode 100644
index 00000000..7699cf72
--- /dev/null
+++ b/docs/demos/en/config-provider/custom-theme.vue
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/config-provider/schema-renderer-theme.vue b/docs/demos/en/config-provider/schema-renderer-theme.vue
new file mode 100644
index 00000000..27a16bdc
--- /dev/null
+++ b/docs/demos/en/config-provider/schema-renderer-theme.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/config-provider/theme.vue b/docs/demos/en/config-provider/theme.vue
new file mode 100644
index 00000000..c0140696
--- /dev/null
+++ b/docs/demos/en/config-provider/theme.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/demos/en/renderer/custom-actions-form.vue b/docs/demos/en/renderer/custom-actions-form.vue
new file mode 100644
index 00000000..fb71b3b8
--- /dev/null
+++ b/docs/demos/en/renderer/custom-actions-form.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/renderer/custom-actions-open-page.vue b/docs/demos/en/renderer/custom-actions-open-page.vue
new file mode 100644
index 00000000..cc07e773
--- /dev/null
+++ b/docs/demos/en/renderer/custom-actions-open-page.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/renderer/required-complete-field-selectors.vue b/docs/demos/en/renderer/required-complete-field-selectors.vue
new file mode 100644
index 00000000..a6f18e36
--- /dev/null
+++ b/docs/demos/en/renderer/required-complete-field-selectors.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/en/renderer/state.vue b/docs/demos/en/renderer/state.vue
new file mode 100644
index 00000000..903f344f
--- /dev/null
+++ b/docs/demos/en/renderer/state.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
diff --git a/docs/demos/renderer/components/user-profile.vue b/docs/demos/renderer/components/user-profile.vue
index 14e48152..597d376a 100644
--- a/docs/demos/renderer/components/user-profile.vue
+++ b/docs/demos/renderer/components/user-profile.vue
@@ -72,4 +72,3 @@ defineProps<{
color: #666;
}
-
diff --git a/docs/demos/renderer/custom-actions-form.vue b/docs/demos/renderer/custom-actions-form.vue
index a7ecd99d..54ff8c97 100644
--- a/docs/demos/renderer/custom-actions-form.vue
+++ b/docs/demos/renderer/custom-actions-form.vue
@@ -1,10 +1,13 @@
-
+
+
+
-
diff --git a/docs/demos/renderer/state.vue b/docs/demos/renderer/state.vue
index bdbebfd5..f0d8d704 100644
--- a/docs/demos/renderer/state.vue
+++ b/docs/demos/renderer/state.vue
@@ -1,10 +1,13 @@
-
+
+
+
-```
-
-### 2. 使用异步组件(推荐)
-
-如果自定义 Renderer 体积较大或需要按需加载,可以使用异步组件:
-
-```vue
-
-```
-
-## 跨框架集成示例
-
-### 集成 Angular Renderer
-
-以下示例展示了如何在 Vue 应用中集成 Angular 渲染器, `tiny-schema-renderer-element-ng`是将 Angular 渲染器包装成了 webComponent
-
-```vue
-
-
-
-
-
-
-
-```
diff --git a/docs/src/components/angular/renderer.md b/docs/src/components/angular/renderer.md
index 624c26ef..7a9674f3 100644
--- a/docs/src/components/angular/renderer.md
+++ b/docs/src/components/angular/renderer.md
@@ -2,6 +2,40 @@
`GenuiRenderer` 是 GenUI SDK 的核心渲染组件(Renderer),用于将大模型返回的结构化 JSON Schema 渲染为可交互的 UI 界面。
+::: warning 物料配置
+`GenuiRenderer` 本身不包含 UI 物料,需配合 `GenuiConfigProvider` 的 `materials` 使用,详见 [安装与配置](../../guide/angular/install#物料配置)。
+
+若需保持旧版「开箱即用」行为,请改用 `GenuiLegacyRenderer`,Input 与内容投影与 `GenuiRenderer` 完全一致。
+:::
+
+## 兼容组件 GenuiLegacyRenderer
+
+`GenuiLegacyRenderer` 内置 OpenTiny NG 默认物料,适用于未配置 `GenuiConfigProvider` 的旧项目迁移,无需额外安装物料包。
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiLegacyRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiLegacyRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'TiButton',
+ props: { color: 'primary' },
+ children: [{ componentName: 'Text', props: { text: '提交' } }],
+ },
+ ],
+ };
+}
+```
+
## Input
### content
@@ -198,7 +232,7 @@ import { MyCustomDirective } from './my-custom-directive';
@Component({
imports: [GenuiRenderer],
template: `
-
+
`,
})
export class GenuiExample {
@@ -237,7 +271,7 @@ import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
@Component({
imports: [GenuiRenderer],
template: `
-
+
`,
})
export class GenuiExample {
@@ -263,7 +297,7 @@ export class GenuiExample {
},
},
showNotification: {
- execute: (params,context) => {
+ execute: (params, context) => {
console.log('通知:', params.message);
},
},
@@ -385,8 +419,8 @@ import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
],
template: `
-
- 生成中 ……
+
+ 生成中 ……
出错了!
卡片标题:{{ schema.componentName }}
diff --git a/docs/src/components/chat.md b/docs/src/components/chat.md
index a9c10527..ce8b0b6d 100644
--- a/docs/src/components/chat.md
+++ b/docs/src/components/chat.md
@@ -4,6 +4,33 @@
仅使用 Chat 时可从 `@opentiny/genui-sdk-vue/chat` 按需引入,见 [快速开始 - 按需引入](../guide/quick-start#按需引入)。
+## 兼容组件 GenuiLegacyChat
+
+::: warning 物料配置(自 1.3.0 起)
+`GenuiChat` 进行了物料解耦重构, 组件已不包含任何组件物料, 需要使用 `GenuiConfigProvider` 注入。
+
+若需保持旧版行为,请改用 `GenuiLegacyChat`(`@opentiny/genui-sdk-vue/legacy-chat`)。
+:::
+
+`GenuiLegacyChat` 内置 OpenTiny 默认物料,适用于未配置 `GenuiConfigProvider` 的旧项目迁移。
+
+```vue
+
+
+
+
+
+```
+
## Props
### url
@@ -482,7 +509,29 @@ interface IChatConfig {
interface ICustomComponentItem extends IGenPromptComponent {
ref?: Component; // 组件引用,用于传给 GenuiRenderer
}
+```
+### ICustomActionItem
+
+```typescript
+interface ICustomActionItem extends IGenPromptAction {
+ execute: (params: any, context: Record) => any;
+}
+
+interface IGenPromptAction {
+ name: string;
+ description?: string;
+ parameters?: JSONSchema;
+ /** 返回值 JSON Schema 描述(可选,无返回值时可省略) */
+ return?: JSONSchema;
+ /** 是否为异步 Action(可选,默认为 false) */
+ async?: boolean;
+}
+```
+
+### IGenPromptComponent
+
+```typescript
interface IGenPromptComponent {
component: string; // 组件名
schema: {
diff --git a/docs/src/components/config-provider.md b/docs/src/components/config-provider.md
index 53200dcf..3f49514f 100644
--- a/docs/src/components/config-provider.md
+++ b/docs/src/components/config-provider.md
@@ -1,6 +1,6 @@
# GenuiConfigProvider 组件
-`GenuiConfigProvider` 用于为渲染器提供主题能力,并将主题样式限定在特定作用域内。
+`GenuiConfigProvider` 用于为渲染器提供主题、国际化与物料配置能力,并将主题样式限定在特定作用域内。
仅使用 ConfigProvider 时可从 `@opentiny/genui-sdk-vue/config-provider` 按需引入,见 [快速开始 - 按需引入](../guide/quick-start#按需引入)。
@@ -97,6 +97,29 @@ const customI18n: I18nMessages = {
查看 [GenuiConfigProvider 组件 - 国际化配置](../examples/config-provider/i18n) 了解详细用法
+### materials
+
+- **类型**: `IMaterials`
+- **必填**: 否(使用 `GenuiRenderer` / `GenuiChat` 时需要配置)
+- **说明**: 渲染器使用的组件物料。通常传入物料包,例如 `@opentiny/genui-sdk-materials-vue-opentiny-vue` 提供的 `materials` 对象。
+
+```vue
+
+
+
+
+
+
+
+```
+
## Slots
`GenuiConfigProvider` 使用默认插槽包裹子组件。
diff --git a/docs/src/components/core/api.md b/docs/src/components/core/api.md
new file mode 100644
index 00000000..f2529b4e
--- /dev/null
+++ b/docs/src/components/core/api.md
@@ -0,0 +1,489 @@
+# API 文档
+
+`@opentiny/genui-sdk-core` 提供 GenUI SDK 的核心能力:协议类型、Prompt 生成、流式 Schema 提取、增量 Patch、JSON 修复等,供 Vue / Angular / Server 等上层包依赖。
+
+## 公共方法
+
+### genPrompt()
+
+根据框架、物料元数据和自定义配置,拼接完整的 System Prompt。
+
+- **类型**
+
+```typescript
+function genPrompt(
+ framework: IGenPromptFramework | IGenPromptFrameworkConfig,
+ materialsMeta: IMaterialsMeta,
+ tgCustomConfig?: IGenPromptCustomConfig,
+ options?: IGenPromptOptions,
+): string
+```
+
+- **参数**
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `framework` | `IGenPromptFramework` \| `IGenPromptFrameworkConfig` | 是 | 框架名(如 `'Vue'`)或自定义框架配置;传字符串时会合并该框架默认 rules |
+| `materialsMeta` | [`IMaterialsMeta`](#imaterialsmeta) | 是 | 物料元数据,通常从物料包的 `meta` 入口引入 |
+| `tgCustomConfig` | [`IGenPromptCustomConfig`](#igenpromptcustomconfig) | 否 | 自定义组件、Snippets、示例、Action |
+| `options` | [`IGenPromptOptions`](#igenpromptoptions) | 否 | 控制 Prompt 各段落是否生成,以及额外 rules |
+
+- **返回值**: `string` — 拼接后的 System Prompt
+
+- **详细信息**
+
+Prompt 通常包含:前缀、可用组件、JSON Schema、示例、Snippets、About This、Actions、生成规则。各段落可通过 `options` 开关裁剪。
+
+- **示例**
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/meta';
+
+const prompt = genPrompt(
+ 'Vue',
+ materialsMeta,
+ {
+ customActions: [
+ {
+ name: 'openPage',
+ description: 'Open a page by path',
+ parameters: {
+ type: 'object',
+ properties: {
+ path: { type: 'string' },
+ },
+ required: ['path'],
+ },
+ },
+ ],
+ },
+ { includeJsonSchema: false },
+);
+```
+
+### PatternExtractor
+
+基于正则状态机,将流式文本拆分为普通内容与被标记包裹的内容。
+
+- **类型**
+
+```typescript
+class PatternExtractor {
+ constructor(config: {
+ onNormalWrite: (value: string) => void;
+ onHandledWrite: (value: string) => void;
+ keepFlag?: false | 'handling' | 'normal';
+ regExpMap?: Record>;
+ })
+
+ setState(state: 'handling' | 'normal'): void
+ reset(): void
+ handleContent(content: string): string
+}
+```
+
+- **参数**(构造函数 `config`)
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `onNormalWrite` | `(value: string) => void` | 是 | 收到普通文本片段时的回调 |
+| `onHandledWrite` | `(value: string) => void` | 是 | 收到标记内(如 schemaJson)文本片段时的回调 |
+| `keepFlag` | `false` \| `'handling'` \| `'normal'` | 否 | 标记本身是否写入对应流;默认不写入 |
+| `regExpMap` | `Record>` | 否 | 自定义起止正则;默认使用 [`SchemaJsonPattern`](#schemajsonpattern) |
+
+- **详细信息**
+
+`handleContent` 处理增量文本,并通过回调分别输出普通流与 handled 流。
+
+- **示例**
+
+```typescript
+import { PatternExtractor } from '@opentiny/genui-sdk-core';
+
+const extractor = new PatternExtractor({
+ onNormalWrite: (chunk) => console.log('markdown:', chunk),
+ onHandledWrite: (chunk) => console.log('schemaJson:', chunk),
+});
+
+extractor.handleContent('hello ```schemaJson\n{"componentName":"Page"');
+extractor.handleContent('\n}\n```');
+```
+
+### SchemaJsonPattern
+
+提供 schemaJson 代码块的完整 / 部分匹配正则。
+
+- **类型**
+
+```typescript
+class SchemaJsonPattern {
+ get regExpMap(): {
+ start: { full: RegExp; partial: RegExp };
+ end: { full: RegExp; partial: RegExp };
+ }
+}
+```
+
+默认 start 标记为 `` ```schemaJson ``,end 标记为 `` ``` ``。可将 `regExpMap` 注入到 `PatternExtractor`。另导出 `getPartialStartRegString(flag: string): string`,用于生成可能被截断的部分匹配正则。
+
+### StreamPatternExtractor
+
+基于 Web Streams 的封装,将输入流拆成 `normalStream` 与 `handledStream`。
+
+- **类型**
+
+```typescript
+class StreamPatternExtractor {
+ static separate(
+ stream: ReadableStream,
+ ): [ReadableStream, ReadableStream]
+
+ get normalStream(): ReadableStream
+ get handledStream(): ReadableStream
+ handleStream(stream: ReadableStream): Promise
+}
+```
+
+- **示例**
+
+```typescript
+import { StreamPatternExtractor } from '@opentiny/genui-sdk-core';
+
+const [normal, handled] = StreamPatternExtractor.separate(inputStream);
+```
+
+### DeltaPatcher
+
+基于 `jsondiffpatch` 对 Schema 做增量合并,并结合缓冲字段选择器过滤不完整字段。
+
+- **类型**
+
+```typescript
+class DeltaPatcher {
+ constructor(options?: IPatchOptions)
+ patchWithDelta(oldValue: Object, newValue: Object, isCompleted: boolean): Object
+}
+```
+
+- **参数**
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `options` | [`IPatchOptions`](#ipatchoptions) | 否 | 构造时传入缓冲字段选择器等配置 |
+| `oldValue` | `Object` | 是 | 当前已合并的 Schema |
+| `newValue` | `Object` | 是 | 新的 Schema 快照 |
+| `isCompleted` | `boolean` | 是 | 流是否结束;为 `true` 时直接全量 patch,不再缓冲 |
+
+- **详细信息**
+
+流式未完成时,命中 `requiredCompleteFieldSelectors` 的路径会被缓冲,直到字段完整再写入。选择器语法与 [`matchJsonPath`](#matchjsonpath) / [`jsonSelectorMatcher`](#jsonselectormatcher) 一致。
+
+查看 [Renderer 配置缓冲字段](../../examples/renderer/required-complete-field-selectors) 了解选择器语法与默认规则。
+
+- **示例**
+
+```typescript
+import { DeltaPatcher } from '@opentiny/genui-sdk-core';
+
+const patcher = new DeltaPatcher({
+ requiredCompleteFieldSelectors: [
+ '[componentName=TinyForm] > props > labelPosition',
+ ],
+});
+
+const schema = {};
+patcher.patchWithDelta(schema, partialSchema, false);
+patcher.patchWithDelta(schema, finalSchema, true);
+```
+
+### matchJsonPath()
+
+判断 JSON 某路径是否匹配 CSS-like 选择器。
+
+- **类型**
+
+```typescript
+function matchJsonPath(
+ json: Record,
+ selector: string,
+ path: string,
+): boolean
+```
+
+- **参数**
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `json` | `Record` | 是 | 完整 JSON 对象,用于解析属性选择器等上下文 |
+| `selector` | `string` | 是 | CSS-like 选择器 |
+| `path` | `string` | 是 | 待匹配的 JSON 路径 |
+
+支持属性选择器 `[key=val]`、`^=` / `$=` / `*=`,伪类 `:empty` / `:object` / `:array` / `:string` / `:number` / `:boolean` / `:null`,以及子组合 `>`。
+
+查看 [Renderer 配置缓冲字段](../../examples/renderer/required-complete-field-selectors) 了解详细用法和选择器语法。
+
+### jsonSelectorMatcher()
+
+判断 delta 路径是否命中缓冲字段选择器,并返回最长匹配路径。
+
+- **类型**
+
+```typescript
+function jsonSelectorMatcher(
+ json: Record,
+ selector: string,
+ lastDeltaKeys: string,
+): { isMatch: boolean; matchPath: string }
+```
+
+- **参数**
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `json` | `Record` | 是 | 当前 JSON 对象 |
+| `selector` | `string` | 是 | 缓冲字段选择器 |
+| `lastDeltaKeys` | `string` | 是 | 本次 delta 变更的路径 |
+
+主要由 `DeltaPatcher` 内部使用,也可在自定义 patch 逻辑中复用。另导出 `findGroupSelector`、`matchSelector`、`matchGroup`。
+
+查看 [Renderer 配置缓冲字段](../../examples/renderer/required-complete-field-selectors) 了解选择器语法。
+
+### repairJson()
+
+尝试解析或修复不完整 / 格式错误的 JSON 字符串。
+
+- **类型**
+
+```typescript
+function repairJson(jsonString: string | undefined): {
+ state: RepairJsonState;
+ value: any | undefined;
+}
+
+function safeJsonParse(jsonString: string): any | undefined
+```
+
+- **参数**
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `jsonString` | `string` \| `undefined` | 是 | 待解析或修复的 JSON 文本 |
+
+- **返回值**
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `state` | [`RepairJsonState`](#repairjsonstate) | 解析结果状态 |
+| `value` | `any` \| `undefined` | 解析成功时的对象;失败为 `undefined` |
+
+- **详细信息**
+
+先 `JSON.parse`;失败则先进行结构修复再走 `jsonrepair`。`safeJsonParse` 仅做安全解析,失败返回 `undefined`。
+
+- **示例**
+
+```typescript
+import { repairJson, RepairJsonState } from '@opentiny/genui-sdk-core';
+
+const { state, value } = repairJson('{"componentName":"Page"');
+if (state === RepairJsonState.SUCCESS || state === RepairJsonState.REPAIRED) {
+ console.log(value);
+}
+```
+
+### buildMaterialDefaultValueMap()
+
+从物料元数据中提取组件属性默认值映射,供 Renderer 合并默认 Props。
+
+- **类型**
+
+```typescript
+function buildMaterialDefaultValueMap(
+ materialsMeta?: Partial,
+): MaterialDefaultValueMap
+```
+
+- **参数**
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `materialsMeta` | `Partial` | 否 | 物料元数据,见 [`IMaterialsMeta`](#imaterialsmeta);缺省时返回空映射 |
+
+- **返回值**: [`MaterialDefaultValueMap`](#materialdefaultvaluemap)
+
+## 类型
+
+### CardSchema
+
+```typescript
+interface JSExpression {
+ type: 'JSExpression';
+ value: string;
+ model?: boolean;
+}
+
+interface JSFunction {
+ type: 'JSFunction';
+ value: string;
+ params?: string[];
+}
+
+type Methods = Record;
+
+interface LifeCycles {
+ onMounted?: JSFunction;
+ onUnmounted?: JSFunction;
+}
+
+interface Node {
+ id?: string;
+ componentName: string;
+ props?: Record;
+ children?: Node[] | string;
+ componentType?: 'Block' | 'PageStart' | 'PageSection';
+ slot?: string | Record;
+ params?: string[];
+ loop?: Record;
+ loopArgs?: string[];
+ condition?: boolean | Record;
+}
+
+type RootNode = Omit & {
+ css?: string;
+ state?: Record;
+ methods?: Methods;
+ lifeCycles?: LifeCycles;
+};
+
+type CardSchema = RootNode;
+type NodeSchema = Node;
+```
+
+### IChatMessage
+
+```typescript
+interface IStreamDelta {
+ reasoning_content?: string | null;
+ content?: string | null;
+ tool_calls?: any;
+ tool_calls_result?: any;
+}
+
+type IMessageItem =
+ | { type: 'schema-card'; content: any; id?: string; state?: Record }
+ | { type: 'markdown'; content: string }
+ | { type: 'reasoning'; content: string; thinking?: boolean }
+ | { type: 'tool'; name: string; status: string; content?: any; [key: string]: any }
+ | { type: string; content: any; [customKey: string]: any };
+
+interface IChatMessage {
+ role: 'assistant';
+ content: string;
+ messages: IMessageItem[];
+ [key: string]: any;
+}
+```
+
+### IMaterials
+
+```typescript
+interface IMaterials {
+ components?: Record; // 组件名 → 运行时组件
+ requiredCompleteFieldSelectors?: string[]; // 缓冲字段选择器
+ defaultPropsMap?: Record; // 组件默认 Props 映射
+ [key: string]: any;
+}
+```
+
+### IMaterialsMeta
+
+```typescript
+interface IExample {
+ id?: string;
+ name: string;
+ description?: string;
+ schema: CardSchema;
+}
+
+interface IMaterialsMeta {
+ materials: IMaterialsProtocol[]; // 物料协议数据
+ examples: IExample[]; // Prompt 示例
+ whiteList: string[]; // 组件白名单
+ wrapperComponent?: string; // 包装组件名,默认如 TinyCard
+ rules?: string[]; // 物料侧生成规则
+}
+```
+
+### MaterialDefaultValueMap
+
+```typescript
+type MaterialDefaultValueMap = Record>; // 组件名 → 属性默认值
+```
+
+### IGenPromptFramework
+
+```typescript
+type IGenPromptFramework = 'Vue' | 'React' | 'Angular' | string;
+```
+
+### IGenPromptFrameworkConfig
+
+```typescript
+interface IGenPromptFrameworkConfig {
+ rules?: string[]; // 框架默认生成规则
+}
+```
+
+### IGenPromptCustomConfig
+
+```typescript
+interface IGenPromptCustomConfig {
+ customComponents?: IGenPromptComponent[]; // 自定义组件描述
+ customSnippets?: IGenPromptSnippet[]; // 自定义 Snippets
+ customExamples?: IGenPromptExample[]; // 自定义示例
+ customActions?: IGenPromptAction[]; // 自定义 Action
+}
+
+interface IGenPromptAction {
+ name: string;
+ description?: string;
+ parameters?: JSONSchema;
+ return?: JSONSchema; // 返回值 JSON Schema(可选)
+ async?: boolean; // 是否为异步 Action,默认 false
+}
+```
+
+### IGenPromptOptions
+
+```typescript
+interface IGenPromptOptions {
+ isSkill?: boolean; // 是否使用 Skill 模式前缀与规则,默认 false
+ includeJsonSchema?: boolean; // 是否包含 JSON Schema 段落,默认 true
+ includeSnippets?: boolean; // 是否包含 Snippets 段落,默认 true
+ includeExamples?: boolean; // 是否包含 Examples 段落,默认 true
+ includeActions?: boolean; // 是否包含 Actions 段落,默认 true
+ includeAboutThis?: boolean; // 是否包含 About This 段落,默认 true
+ includeBaseRules?: boolean; // 是否包含基础规则,默认 true
+ rules?: string[]; // 额外规则,会与物料 rules、框架默认 rules 合并
+}
+```
+
+### IPatchOptions
+
+```typescript
+interface IPatchOptions {
+ requiredCompleteFieldSelectors?: string[]; // 缓冲字段选择器
+}
+```
+
+### RepairJsonState
+
+```typescript
+enum RepairJsonState {
+ INVALID_INPUT = 'invalid-input', // 输入无效
+ SUCCESS = 'success-parse', // 直接解析成功
+ REPAIRED = 'repaired-parse', // 修复后解析成功
+ FAILED = 'failed-repair', // 修复失败
+}
+```
diff --git a/docs/src/components/materials/angular-opentiny-ng.md b/docs/src/components/materials/angular-opentiny-ng.md
new file mode 100644
index 00000000..8841f4fe
--- /dev/null
+++ b/docs/src/components/materials/angular-opentiny-ng.md
@@ -0,0 +1,40 @@
+# Angular OpenTiny NG
+
+`@opentiny/genui-sdk-materials-angular-opentiny-ng` 基于 [OpenTiny NG](https://opentiny.design/tiny-ng/) 的物料包,提供运行时组件映射与 Prompt 元数据。
+
+类型定义见 [Core - IMaterials](../core/api#imaterials) / [IMaterialsMeta](../core/api#imaterialsmeta)。
+
+## 导出
+
+| 入口 | 导出 |
+|------|------|
+| `.` | `materials`、`materialsMeta` |
+| `./materials` | `materials` |
+| `./meta` | `materialsMeta` |
+
+## materials
+
+- **类型**: `IMaterials`
+- **说明**: OpenTiny NG 组件映射,注入 ConfigProvider。
+
+```typescript
+import { materials } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/materials';
+```
+
+```html
+
+
+
+```
+
+## materialsMeta
+
+- **类型**: `IMaterialsMeta`
+- **说明**: 供服务端 [`genPrompt`](../core/api#genprompt) 使用。`wrapperComponent` 默认为 `TiCard`。
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/meta';
+
+const systemPrompt = genPrompt('Angular', materialsMeta);
+```
diff --git a/docs/src/components/materials/vue-element-plus.md b/docs/src/components/materials/vue-element-plus.md
new file mode 100644
index 00000000..b0135b2d
--- /dev/null
+++ b/docs/src/components/materials/vue-element-plus.md
@@ -0,0 +1,42 @@
+# Vue Element Plus
+
+`@opentiny/genui-sdk-materials-vue-element-plus` 基于 [Element Plus](https://element-plus.org/) 的物料包,提供运行时组件映射与 Prompt 元数据。
+
+类型定义见 [Core - IMaterials](../core/api#imaterials) / [IMaterialsMeta](../core/api#imaterialsmeta)。
+
+## 导出
+
+| 入口 | 导出 |
+|------|------|
+| `.` | `materials`、`materialsMeta` |
+| `./materials` | `materials` |
+| `./meta` | `materialsMeta` |
+
+## materials
+
+- **类型**: `IMaterials`
+- **说明**: Element Plus 组件映射,注入 [GenuiConfigProvider](../config-provider#materials)。
+
+```typescript
+import 'element-plus/dist/index.css';
+import { materials } from '@opentiny/genui-sdk-materials-vue-element-plus/materials';
+import { GenuiChat, GenuiConfigProvider } from '@opentiny/genui-sdk-vue';
+```
+
+```vue
+
+
+
+```
+
+## materialsMeta
+
+- **类型**: `IMaterialsMeta`
+- **说明**: 供服务端 [`genPrompt`](../core/api#genprompt) 使用。`wrapperComponent` 默认为 `ElCard`。
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-element-plus/meta';
+
+const systemPrompt = genPrompt('Vue', materialsMeta);
+```
diff --git a/docs/src/components/materials/vue-opentiny-vue.md b/docs/src/components/materials/vue-opentiny-vue.md
new file mode 100644
index 00000000..db2b4702
--- /dev/null
+++ b/docs/src/components/materials/vue-opentiny-vue.md
@@ -0,0 +1,41 @@
+# Vue OpenTiny Vue
+
+`@opentiny/genui-sdk-materials-vue-opentiny-vue` 基于 [OpenTiny Vue](https://opentiny.design/tiny-vue/) 的物料包,提供运行时组件映射与 Prompt 元数据。
+
+类型定义见 [Core - IMaterials](../core/api#imaterials) / [IMaterialsMeta](../core/api#imaterialsmeta)。
+
+## 导出
+
+| 入口 | 导出 |
+|------|------|
+| `.` | `materials`、`miniMaterials`、`materialsMeta`、`miniMaterialsMeta` |
+| `./materials` | `materials`、`miniMaterials` |
+| `./meta` | `materialsMeta`、`miniMaterialsMeta` |
+
+## materials / miniMaterials
+
+- **类型**: `IMaterials`
+- **说明**: OpenTiny Vue 组件映射,注入 [GenuiConfigProvider](../config-provider#materials)。`miniMaterials` 为精简组件集(不含图表等)。
+
+```typescript
+import { materials } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/materials';
+import { GenuiChat, GenuiConfigProvider } from '@opentiny/genui-sdk-vue';
+```
+
+```vue
+
+
+
+```
+
+## materialsMeta / miniMaterialsMeta
+
+- **类型**: `IMaterialsMeta`
+- **说明**: 供服务端 [`genPrompt`](../core/api#genprompt) 使用。`wrapperComponent` 默认为 `TinyCard`。`miniMaterialsMeta` 对应精简组件的物料。
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/meta';
+
+const systemPrompt = genPrompt('Vue', materialsMeta);
+```
diff --git a/docs/src/components/renderer.md b/docs/src/components/renderer.md
index 6efc628f..26aa18c4 100644
--- a/docs/src/components/renderer.md
+++ b/docs/src/components/renderer.md
@@ -4,6 +4,36 @@
仅使用 Renderer 时可从 `@opentiny/genui-sdk-vue/renderer` 按需引入,见 [快速开始 - 按需引入](../guide/quick-start#按需引入)。
+## 兼容组件 GenuiLegacyRenderer
+
+::: warning 物料配置(自 1.3.0 起)
+`GenuiRenderer` 进行了物料解耦重构,组件已不包含任何组件物料,需要使用 `GenuiConfigProvider` 注入。
+
+若需保持旧版行为,请改用 `GenuiLegacyRenderer`(`@opentiny/genui-sdk-vue/legacy-renderer`)。
+:::
+
+`GenuiLegacyRenderer` 内置 OpenTiny 默认物料,适用于未配置 `GenuiConfigProvider` 的旧项目迁移。
+
+```vue
+
+
+
+
+
+```
+
## Props
### content
diff --git a/docs/src/components/server/cli.md b/docs/src/components/server/cli.md
index 44b1019a..4704a20d 100644
--- a/docs/src/components/server/cli.md
+++ b/docs/src/components/server/cli.md
@@ -32,7 +32,7 @@ genui-sdk-server
服务启动成功后,会输出服务器地址,例如:
-```
+```text
genui-sdk-server is running on http://localhost:3100
```
diff --git a/docs/src/en/components/angular/renderer.md b/docs/src/en/components/angular/renderer.md
new file mode 100644
index 00000000..7f232760
--- /dev/null
+++ b/docs/src/en/components/angular/renderer.md
@@ -0,0 +1,485 @@
+# GenuiRenderer Component
+
+`GenuiRenderer` is the core rendering component (Renderer) of GenUI SDK. It renders structured JSON Schema returned by large language models into interactive UI.
+
+::: warning Materials required
+`GenuiRenderer` does not include UI materials. Use it with `GenuiConfigProvider`'s `materials` prop. See [Installation](../../guide/angular/install#materials-configuration).
+
+For the previous out-of-the-box behavior, use `GenuiLegacyRenderer` instead. Its inputs and content projection are identical to `GenuiRenderer`.
+:::
+
+## Compatibility Component: GenuiLegacyRenderer
+
+`GenuiLegacyRenderer` bundles OpenTiny NG default materials. Use it when migrating old projects that did not configure `GenuiConfigProvider`. No extra materials package is required.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiLegacyRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiLegacyRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'TiButton',
+ props: { color: 'primary' },
+ children: [{ componentName: 'Text', props: { text: 'Submit' } }],
+ },
+ ],
+ };
+}
+```
+
+## Input
+
+### content
+
+- **Type**: `string | object`
+- **Required**: Yes
+- **Description**: Schema content as a string or object. When a string is passed, the component attempts to parse "partial JSON" and auto-complete it, supporting streaming updates.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ },
+ },
+ ],
+ };
+}
+```
+
+### isJsonComplete
+
+- **Type**: `boolean`
+- **Required**: No
+- **Description**: Applies only when `content` is a JSON object. Marks whether the current JSON is complete, helping the buffer logic determine whether values are complete.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ style: 'color:'
+ },
+ },
+ ],
+ };
+ isJsonComplete = false;
+}
+```
+
+### generating
+
+- **Type**: `boolean`
+- **Required**: No
+- **Description**: Indicates whether the current conversation is still generating. Used to control UI loading state.
+
+```ts
+
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ },
+ },
+ ],
+ };
+ isGenerating = true;
+}
+```
+
+### customComponents
+
+- **Type**: `Record>`
+- **Required**: No
+- **Description**: Custom component map for extending the available component list.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { MyCustomComponent } from './my-custom-component';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'MyCustomComponent',
+ props: {
+ foo: 'bar',
+ },
+ },
+ ],
+ };
+ customComponents = {
+ MyCustomComponent: MyCustomComponent,
+ // ...
+ };
+}
+```
+
+#### Notes
+
+- Non-`standalone` components must be used together with `customComponentsModule`.
+- Component metadata must be sent to the backend service when calling the API so the model can generate matching protocol JSON for the component.
+- ⚠️ Limitation: Dynamic rendering does not currently support components queried via `@ContentChild` or `@ContentChildren`.
+
+
+### customComponentsModule
+
+- **Type**: `Record>`
+- **Required**: No
+- **Description**: Module map for custom components. Required when using non-`standalone` components.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { MyCustomModule, MyCustomComponent } from './my-custom-module';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'MyCustomComponent',
+ props: {
+ foo: 'bar',
+ },
+ },
+ ],
+ };
+ customComponents = {
+ MyCustomComponent: MyCustomComponent,
+ // ...
+ };
+ customComponentsModule = {
+ MyCustomComponent: MyCustomModule,
+ // ...
+ }
+}
+```
+
+### customDirectives
+
+- **Type**: `Record>`
+- **Required**: No
+- **Description**: Directive map for extending the available directive list.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { MyCustomDirective } from './my-custom-directive';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'div',
+ directives: [
+ {
+ directiveName: 'MyCustomDirective'
+ }
+ ]
+ },
+ ],
+ };
+ customDirectives = {
+ MyCustomDirective: MyCustomDirective,
+ // ...
+ };
+}
+```
+
+⚠️ Limitation: Due to the `ViewContainerRef.createComponent` API, only `standalone` directives are currently supported.
+
+### customActions
+
+- **Type**: `Record void }>`
+- **Required**: No
+- **Description**: Custom action map defining actions that can be invoked from components.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ onClick: {
+ type: 'JSFunction',
+ value: 'function() { this.callAction(\'showNotification\', { message: \'User clicked HelloWorld\'})}'
+ }
+ },
+ },
+ ],
+ };
+ customActions = {
+ openPage: {
+ execute: (params, context) => {
+ window.open(params.url, params.target || '_self');
+ },
+ },
+ showNotification: {
+ execute: (params, context) => {
+ console.log('Notification:', params.message);
+ },
+ },
+ };
+}
+
+```
+
+
+See [Renderer - Custom Actions](../../examples/angular/renderer/custom-actions) for detailed usage.
+
+### requiredCompleteFieldSelectors
+
+- **Type**: `string[]`
+- **Required**: No
+- **Description**: Specifies which field paths must be complete before updates are applied. Used to control buffering strategy during streaming updates.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ onClick: {
+ type: 'JSFunction',
+ value: 'function() { this.callAction(\'showNotification\', { message: \'User clicked HelloWorld\'})}'
+ }
+ },
+ },
+ ],
+ };
+
+ requiredCompleteFieldSelectors = [
+ '[componentName=Text] > props > onClick'
+ ];
+}
+```
+
+See [Renderer - Buffer Field Configuration](../../examples/angular/renderer/required-complete-field-selectors) for detailed usage.
+
+### state
+
+- **Type**: `Record`
+- **Required**: No
+- **Description**: Global state passed to the renderer, accessible in components via context.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ state: {
+ userId: null,
+ userName: ''
+ },
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: {
+ type: 'JSExpression',
+ value: 'this.state.userName'
+ }
+ },
+ },
+ ],
+ };
+
+ // Restore from some history record
+ state = this.getFromCache();
+ getFromCache() {
+ return {
+ userId: 123,
+ userName: 'John'
+ }
+ }
+}
+
+```
+
+See [Renderer - Passing and Merging State](../../examples/angular/renderer/state) for detailed usage.
+
+## Template
+
+### header
+
+- **Context**: `{ schema: CardSchema, isError: boolean, isFinished: boolean }`
+- **Description**: Custom renderer header content
+
+```ts
+import { Component } from '@angular/core';
+import { CommonModule } from '@angular/common'
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [
+ CommonModule,
+ GenuiRenderer
+ ],
+ template: `
+
+
+ Generating...
+ Error!
+ Card title: {{ schema.componentName }}
+
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ },
+ },
+ ],
+ };
+}
+```
+
+### footer
+
+- **Parameters**: `{ schema: CardSchema, isError: boolean, isFinished: boolean }`
+- **Description**: Custom renderer footer content
+
+```ts
+import { Component } from '@angular/core';
+import { CommonModule } from '@angular/common'
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [
+ CommonModule,
+ GenuiRenderer
+ ],
+ template: `
+
+
+ Print schema
+
+
+ `,
+})
+export class GenuiExample {
+ schemaContent = {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'Text',
+ props: {
+ text: 'Hello World',
+ },
+ },
+ ],
+ };
+ handlePrint(schema: any) {
+ console.log(schema);
+ }
+}
+```
+
diff --git a/docs/src/en/components/chat.md b/docs/src/en/components/chat.md
new file mode 100644
index 00000000..377ff8dd
--- /dev/null
+++ b/docs/src/en/components/chat.md
@@ -0,0 +1,647 @@
+# GenuiChat Component
+
+`GenuiChat` is an integrated TinyRobot chat component that wraps session management, streaming responses, generation state, and more, providing an out-of-the-box chat experience.
+
+When using only Chat, you can import it on demand from `@opentiny/genui-sdk-vue/chat`. See [Quick Start - Subpath Imports](../guide/quick-start#subpath-imports).
+
+## Compatibility Component: GenuiLegacyChat
+
+::: warning Materials configuration (since v1.3.0)
+`GenuiChat` has been refactored to decouple materials. The component no longer includes any UI materials; inject them via `GenuiConfigProvider`.
+
+For previous behavior, use `GenuiLegacyChat` (`@opentiny/genui-sdk-vue/legacy-chat`) instead.
+:::
+
+`GenuiLegacyChat` bundles OpenTiny default materials. Use it when migrating old projects that did not configure `GenuiConfigProvider`.
+
+```vue
+
+
+
+
+
+```
+
+## Props
+
+### url
+
+- **Type**: `string`
+- **Required**: No
+- **Description**: Backend service URL for requesting structured data from the large language model.
+
+```vue
+
+
+
+```
+
+### model
+
+- **Type**: `string`
+- **Required**: No
+- **Description**: Large language model name.
+
+```vue
+
+
+
+```
+
+### temperature
+
+- **Type**: `number`
+- **Required**: No
+- **Default**: `0.3`
+- **Description**: Model temperature parameter controlling output randomness.
+
+```vue
+
+
+
+```
+
+### messages
+
+- **Type**: `IMessage[]`
+- **Required**: No
+- **Default**: `[]`
+- **Description**: Initial conversation context.
+
+```vue
+
+
+
+
+
+```
+
+### chatConfig
+
+- **Type**: `IChatConfig`
+- **Required**: No
+- **Description**: Chat-related configuration.
+
+```vue
+
+
+
+
+
+```
+
+### customComponents
+
+- **Type**: `ICustomComponentItem[]`
+- **Required**: No
+- **Description**: Custom component array. Each item includes a schema definition and an optional `ref` (component reference).
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Components](../examples/chat/custom-components) for detailed usage.
+
+### customSnippets
+
+- **Type**: `IGenPromptSnippet[]`
+- **Required**: No
+- **Description**: Custom snippet array providing common component composition patterns.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Snippets](../examples/chat/custom-snippets) for detailed usage.
+
+### customExamples
+
+- **Type**: `IGenPromptExample[]`
+- **Required**: No
+- **Description**: Custom example array providing component usage examples.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Examples](../examples/chat/custom-examples) for detailed usage.
+
+### customActions
+
+- **Type**: `any[]`
+- **Required**: No
+- **Description**: Custom action array defining actions that can be invoked from components.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Actions](../examples/chat/custom-actions) for detailed usage.
+
+### rendererSlots
+
+- **Type**: `IRendererSlots`
+- **Required**: No
+- **Description**: Slots passed through to `GenuiRenderer`.
+
+```vue
+
+
+
+
+
+```
+
+### thinkComponent
+
+- **Type**: `Component`
+- **Required**: No
+- **Description**: Custom thinking process component.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Thinking Process](../examples/chat/thinking-process) for detailed usage and component prop types.
+
+### roles
+
+- **Type**: `IRolesConfig`
+- **Required**: No
+- **Description**: Custom role configuration including avatars and styles for user and assistant.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Footer Toolbar](../examples/chat/footer-toolbar) for detailed usage.
+
+### features
+
+- **Type**: `ModelCapability`
+- **Required**: No
+- **Description**: Model capability configuration, such as image upload and function calling support.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Image Upload](../examples/chat/image-upload) for detailed usage.
+
+### customFetch
+
+- **Type**: `CustomFetch`
+- **Required**: No
+- **Description**: Custom fetch function for fully customizing HTTP request behavior. Useful for integrating third-party SDKs, adding authentication, handling tool calls, implementing custom streaming responses, and similar scenarios.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Custom Fetch](../examples/chat/custom-fetch) for detailed usage.
+
+### requiredCompleteFieldSelectors
+
+- **Type**: `string[]`
+- **Required**: No
+- **Description**: Buffer field selector array specifying which field paths must be complete before updates are applied. This prop is passed through to `GenuiRenderer` to prevent render errors caused by incomplete fields during streaming.
+
+```vue
+
+
+
+
+
+```
+
+See [Renderer - Buffer Fields](../examples/renderer/required-complete-field-selectors) for detailed usage and selector syntax.
+
+## Slots
+
+### empty
+
+- **Description**: Custom empty state slot. Rendered when there is no conversation content, useful for welcome text, onboarding copy, or placeholder UI.
+- **Slot parameters**: None
+
+```vue
+
+
+
+
+
Welcome to GenuiChat
+
+
+
+
+
+
+```
+
+## Methods
+
+### getConversation
+
+- **Return type**: `UseConversationReturn`
+- **Description**: Returns the conversation manager object for session APIs, including conversation list, current session, save/load, and related features.
+
+```vue
+
+
+
+
+
+```
+
+See [Chat - Conversation History](../examples/chat/history) for detailed usage.
+
+## Types
+
+### IMessage
+
+```typescript
+interface IMessage {
+ role: 'user' | 'assistant';
+ content: string;
+ messages?: IMessageItem[]; // Custom display content
+}
+
+interface IMessageItem {
+ type: string;
+ content: string;
+ [customKey: string]: any;
+}
+```
+
+### IChatConfig
+
+```typescript
+interface IChatConfig {
+ addToolCallContext?: boolean; // Whether to add tool call context
+ showThinkingResult?: boolean; // Whether to show thinking result
+}
+```
+
+### ICustomComponentItem
+
+```typescript
+interface ICustomComponentItem extends IGenPromptComponent {
+ ref?: Component; // Component reference passed to GenuiRenderer
+}
+
+interface IGenPromptComponent {
+ component: string; // Component name
+ schema: {
+ properties?: IGenPromptComponentProperty[];
+ events?: IGenPromptComponentEvent[];
+ slots?: Record;
+ };
+ name?: string; // Component label
+ description?: string;
+}
+
+interface IGenPromptComponentProperty {
+ property: string;
+ description: string;
+ type: string;
+ required?: boolean; // Default false
+ defaultValue?: any; // Default empty
+ properties?: IGenPromptComponentProperty[];
+}
+
+interface IGenPromptComponentEvent {
+ type: string;
+ functionInfo?: IFunctionInfo;
+ defaultValue?: string;
+ description: string;
+}
+
+interface IFunctionInfo {
+ params: IFunctionParam[];
+ returns: Record;
+}
+
+interface IFunctionParam {
+ name: string;
+ type: string;
+ defaultValue: string;
+ description: string;
+}
+```
+
+### IGenPromptSnippet
+
+```typescript
+type IGenPromptSnippet = NodeSchema;
+
+interface NodeSchema {
+ componentName: string;
+ props?: Record;
+ children?: NodeSchema[];
+ [key: string]: any;
+}
+```
+
+### IGenPromptExample
+
+```typescript
+interface IGenPromptExample {
+ name: string;
+ description?: string;
+ schema: CardSchema;
+}
+
+interface CardSchema {
+ componentName: 'Page';
+ props?: Record;
+ children?: NodeSchema[];
+ [key: string]: any;
+}
+```
+
+### ModelCapability
+
+```typescript
+interface ModelCapability {
+ supportImage?: ImageFeatures;
+ supportFunctionCalling?: boolean;
+ [key: string]: any;
+}
+
+interface ImageFeatures {
+ enabled: boolean;
+ maxImageSize: number; // MB
+ maxFilesPerRequest: number;
+ supportedFileTypes: string[];
+}
+```
+
+### IRolesConfig
+
+```typescript
+interface IRolesConfig {
+ user: BubbleRoleConfig; // User role config
+ assistant: BubbleRoleConfig; // Assistant role config
+}
+
+interface BubbleRoleConfig {
+ placement?: 'start' | 'end'; // Message bubble placement
+ avatar?: Component | VNode; // Avatar component
+ maxWidth?: string; // Maximum message width
+ slots?: {
+ // Slot config, e.g. footer toolbar
+ trailer?: Component;
+ };
+}
+
+interface IBubbleSlotsProps {
+ index: number;
+ bubbleProps: BubbleProps;
+ isFinished: boolean;
+ messageManager: UseMessageReturn;
+ chatMessage: IMessage
+}
+```
+
+### CustomFetch
+
+```typescript
+type CustomFetch = (
+ url: string,
+ options: {
+ method: string;
+ headers: Record;
+ body: string;
+ signal?: AbortSignal;
+ },
+) => Promise | Response;
+```
+
+See TinyRobot documentation for `BubbleProps`, `UseConversationReturn`, and `UseMessageReturn`.
+
+See [BubbleProps](https://docs.opentiny.design/tiny-robot/guide/bubble.html#props) for definitions and usage.
+
+See [UseConversationReturn](https://docs.opentiny.design/tiny-robot/guide/conversation.html#%E8%BF%94%E5%9B%9E%E5%80%BC) for definitions and usage.
+
+See [UseMessageReturn](https://docs.opentiny.design/tiny-robot/guide/message.html#%E8%BF%94%E5%9B%9E%E5%80%BC) for definitions and usage.
diff --git a/docs/src/en/components/config-provider.md b/docs/src/en/components/config-provider.md
new file mode 100644
index 00000000..79cc011a
--- /dev/null
+++ b/docs/src/en/components/config-provider.md
@@ -0,0 +1,190 @@
+# GenuiConfigProvider Component
+
+`GenuiConfigProvider` provides theme, i18n, and materials configuration for the renderer, and scopes theme styles within a specific container.
+
+When using only ConfigProvider, you can import it on demand from `@opentiny/genui-sdk-vue/config-provider`. See [Quick Start - Subpath Imports](../guide/quick-start#subpath-imports).
+
+When used with `GenuiRenderer` or `GenuiChat`, you typically need to inject component materials via the `materials` prop. See [Materials Configuration](../guide/quick-start#materials-configuration).
+
+## Props
+
+### theme
+
+- **Type**: `'dark' | 'lite' | 'light' | 'auto'`
+- **Required**: No
+- **Default**: `'light'`
+- **Description**: Theme mode.
+ - `'dark'`: Dark theme
+ - `'lite'`: Lite theme
+ - `'light'`: Light theme
+ - `'auto'`: Follow the browser preference automatically
+
+```vue
+
+
+
+
+
+```
+
+See [GenuiConfigProvider - Theme Switching](../examples/config-provider/theme) for detailed usage.
+
+### id
+
+- **Type**: `string`
+- **Required**: No
+- **Default**: `'tiny-genui-config-provider'`
+- **Description**: The container element id used for style scoping. When multiple `GenuiConfigProvider` instances exist on the page, set a different id for each.
+
+```vue
+
+
+
+
+
+```
+
+See [GenuiConfigProvider - Custom Theme](../examples/config-provider/custom-theme) for detailed usage.
+
+### locale
+
+- **Type**: `string`
+- **Required**: No
+- **Default**: `'zh_CN'`
+- **Description**: Sets the component locale. Supported language codes include `'zh_CN'` (Simplified Chinese) and `'en_US'` (English).
+
+```vue
+
+
+
+
+
+```
+
+### i18n
+
+- **Type**: `I18nMessages`
+- **Required**: No
+- **Default**: `undefined`
+- **Description**: Custom internationalization message object. Used to override or extend default i18n text. Format: `{ [lang: string]: { [key: string]: string | I18nMessageObject } }`.
+
+```vue
+
+
+
+
+
+
+
+```
+
+See [GenuiConfigProvider - i18n Configuration](../examples/config-provider/i18n) for detailed usage.
+
+### materials
+
+- **Type**: `IMaterials`
+- **Required**: No (required when using `GenuiRenderer` / `GenuiChat`)
+- **Description**: Component materials for the renderer. Usually pass materials from a materials package, e.g. the `materials` object from `@opentiny/genui-sdk-materials-vue-opentiny-vue`.
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Slots
+
+`GenuiConfigProvider` uses the default slot to wrap child components.
+
+### Customizing theme for GenuiChat
+
+```vue
+
+
+
+
+ Toggle theme
+
+
+
+```
+
+### Customizing theme for GenuiRenderer
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Types
+
+### I18nMessages
+
+```typescript
+type I18nMessages = {
+ [lang: string]: I18nMessageObject;
+};
+```
+
+Internationalization message object. Keys are language codes (e.g. `'zh_CN'`, `'en_US'`), and values are message objects for that language.
+
+### I18nMessageObject
+
+```typescript
+type I18nMessageObject = {
+ [key: string]: string | I18nMessageObject;
+};
+```
+
+Internationalization message object structure supporting nested objects. Keys are message keys; values are strings or nested message objects.
diff --git a/docs/src/en/components/core/api.md b/docs/src/en/components/core/api.md
new file mode 100644
index 00000000..83299ccb
--- /dev/null
+++ b/docs/src/en/components/core/api.md
@@ -0,0 +1,490 @@
+# API Reference
+
+`@opentiny/genui-sdk-core` provides the core capabilities of GenUI SDK: protocol types, prompt generation, streaming schema extraction, delta patching, JSON repair, and more. It is consumed by Vue / Angular / Server packages.
+
+
+## Public APIs
+
+### genPrompt()
+
+Builds a full system prompt from framework, materials metadata, and optional custom config.
+
+- **Type**
+
+```typescript
+function genPrompt(
+ framework: IGenPromptFramework | IGenPromptFrameworkConfig,
+ materialsMeta: IMaterialsMeta,
+ tgCustomConfig?: IGenPromptCustomConfig,
+ options?: IGenPromptOptions,
+): string
+```
+
+- **Parameters**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `framework` | `IGenPromptFramework` \| `IGenPromptFrameworkConfig` | Yes | Framework name (e.g. `'Vue'`) or custom framework config; string form merges that framework’s default rules |
+| `materialsMeta` | [`IMaterialsMeta`](#imaterialsmeta) | Yes | Materials metadata, usually imported from a materials package `meta` entry |
+| `tgCustomConfig` | [`IGenPromptCustomConfig`](#igenpromptcustomconfig) | No | Custom components, snippets, examples, and actions |
+| `options` | [`IGenPromptOptions`](#igenpromptoptions) | No | Toggle prompt sections and append extra rules |
+
+- **Returns**: `string` — the assembled system prompt
+
+- **Details**
+
+A prompt typically includes: prefix, available components, JSON Schema, examples, snippets, About This, actions, and generation rules. Use `options` to include or omit sections.
+
+- **Example**
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/meta';
+
+const prompt = genPrompt(
+ 'Vue',
+ materialsMeta,
+ {
+ customActions: [
+ {
+ name: 'openPage',
+ description: 'Open a page by path',
+ parameters: {
+ type: 'object',
+ properties: {
+ path: { type: 'string' },
+ },
+ required: ['path'],
+ },
+ },
+ ],
+ },
+ { includeJsonSchema: false },
+);
+```
+
+### PatternExtractor
+
+A regex state machine that splits streaming text into normal content and marked content.
+
+- **Type**
+
+```typescript
+class PatternExtractor {
+ constructor(config: {
+ onNormalWrite: (value: string) => void;
+ onHandledWrite: (value: string) => void;
+ keepFlag?: false | 'handling' | 'normal';
+ regExpMap?: Record>;
+ })
+
+ setState(state: 'handling' | 'normal'): void
+ reset(): void
+ handleContent(content: string): string
+}
+```
+
+- **Parameters** (`config`)
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `onNormalWrite` | `(value: string) => void` | Yes | Callback for normal text chunks |
+| `onHandledWrite` | `(value: string) => void` | Yes | Callback for text inside markers (e.g. schemaJson) |
+| `keepFlag` | `false` \| `'handling'` \| `'normal'` | No | Whether markers themselves are written to a stream; default off |
+| `regExpMap` | `Record>` | No | Custom start/end regexes; defaults to [`SchemaJsonPattern`](#schemajsonpattern) |
+
+- **Details**
+
+`handleContent` processes incremental text and emits chunks via callbacks.
+
+- **Example**
+
+```typescript
+import { PatternExtractor } from '@opentiny/genui-sdk-core';
+
+const extractor = new PatternExtractor({
+ onNormalWrite: (chunk) => console.log('markdown:', chunk),
+ onHandledWrite: (chunk) => console.log('schemaJson:', chunk),
+});
+
+extractor.handleContent('hello ```schemaJson\n{"componentName":"Page"');
+extractor.handleContent('\n}\n```');
+```
+
+### SchemaJsonPattern
+
+Provides full / partial match regexes for schemaJson fenced blocks.
+
+- **Type**
+
+```typescript
+class SchemaJsonPattern {
+ get regExpMap(): {
+ start: { full: RegExp; partial: RegExp };
+ end: { full: RegExp; partial: RegExp };
+ }
+}
+```
+
+Default start marker is `` ```schemaJson ``, end marker is `` ``` ``. Inject `regExpMap` into `PatternExtractor` when needed. Also exports `getPartialStartRegString(flag: string): string` for truncated prefix matching.
+
+### StreamPatternExtractor
+
+Web Streams wrapper that forks an input stream into `normalStream` and `handledStream`.
+
+- **Type**
+
+```typescript
+class StreamPatternExtractor {
+ static separate(
+ stream: ReadableStream,
+ ): [ReadableStream, ReadableStream]
+
+ get normalStream(): ReadableStream
+ get handledStream(): ReadableStream
+ handleStream(stream: ReadableStream): Promise
+}
+```
+
+- **Example**
+
+```typescript
+import { StreamPatternExtractor } from '@opentiny/genui-sdk-core';
+
+const [normal, handled] = StreamPatternExtractor.separate(inputStream);
+```
+
+### DeltaPatcher
+
+Merges schema objects incrementally with `jsondiffpatch`, filtering incomplete fields via buffer-field selectors.
+
+- **Type**
+
+```typescript
+class DeltaPatcher {
+ constructor(options?: IPatchOptions)
+ patchWithDelta(oldValue: Object, newValue: Object, isCompleted: boolean): Object
+}
+```
+
+- **Parameters**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `options` | [`IPatchOptions`](#ipatchoptions) | No | Constructor options such as buffer-field selectors |
+| `oldValue` | `Object` | Yes | Current merged schema |
+| `newValue` | `Object` | Yes | New schema snapshot |
+| `isCompleted` | `boolean` | Yes | Whether the stream has finished; `true` patches eagerly without buffering |
+
+- **Details**
+
+While streaming, paths matching `requiredCompleteFieldSelectors` are buffered until complete. Selector syntax matches [`matchJsonPath`](#matchjsonpath) / [`jsonSelectorMatcher`](#jsonselectormatcher).
+
+See [Renderer - Buffer Field Configuration](../../examples/renderer/required-complete-field-selectors) for selector syntax and defaults.
+
+- **Example**
+
+```typescript
+import { DeltaPatcher } from '@opentiny/genui-sdk-core';
+
+const patcher = new DeltaPatcher({
+ requiredCompleteFieldSelectors: [
+ '[componentName=TinyForm] > props > labelPosition',
+ ],
+});
+
+const schema = {};
+patcher.patchWithDelta(schema, partialSchema, false);
+patcher.patchWithDelta(schema, finalSchema, true);
+```
+
+### matchJsonPath()
+
+Checks whether a JSON path matches a CSS-like selector.
+
+- **Type**
+
+```typescript
+function matchJsonPath(
+ json: Record,
+ selector: string,
+ path: string,
+): boolean
+```
+
+- **Parameters**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `json` | `Record` | Yes | Full JSON object for attribute-selector context |
+| `selector` | `string` | Yes | CSS-like selector |
+| `path` | `string` | Yes | JSON path to test |
+
+Supports attribute selectors `[key=val]`, `^=` / `$=` / `*=`, pseudos `:empty` / `:object` / `:array` / `:string` / `:number` / `:boolean` / `:null`, and child combinator `>`.
+
+See [Renderer - Buffer Field Configuration](../../examples/renderer/required-complete-field-selectors) for detailed usage and selector syntax.
+
+### jsonSelectorMatcher()
+
+Checks whether a delta path hits a buffer-field selector and returns the longest match path.
+
+- **Type**
+
+```typescript
+function jsonSelectorMatcher(
+ json: Record,
+ selector: string,
+ lastDeltaKeys: string,
+): { isMatch: boolean; matchPath: string }
+```
+
+- **Parameters**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `json` | `Record` | Yes | Current JSON object |
+| `selector` | `string` | Yes | Buffer-field selector |
+| `lastDeltaKeys` | `string` | Yes | Path of the current delta change |
+
+Used mainly by `DeltaPatcher`; reusable in custom patch logic. Also exports `findGroupSelector`, `matchSelector`, `matchGroup`.
+
+See [Renderer - Buffer Field Configuration](../../examples/renderer/required-complete-field-selectors) for selector syntax.
+
+### repairJson()
+
+Parses or repairs incomplete / malformed JSON strings.
+
+- **Type**
+
+```typescript
+function repairJson(jsonString: string | undefined): {
+ state: RepairJsonState;
+ value: any | undefined;
+}
+
+function safeJsonParse(jsonString: string): any | undefined
+```
+
+- **Parameters**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `jsonString` | `string` \| `undefined` | Yes | JSON text to parse or repair |
+
+- **Returns**
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `state` | [`RepairJsonState`](#repairjsonstate) | Parse result state |
+| `value` | `any` \| `undefined` | Parsed object on success; `undefined` on failure |
+
+- **Details**
+
+Tries `JSON.parse` first; on failure, applies structural fixes then `jsonrepair`. `safeJsonParse` only parses safely and returns `undefined` on failure.
+
+- **Example**
+
+```typescript
+import { repairJson, RepairJsonState } from '@opentiny/genui-sdk-core';
+
+const { state, value } = repairJson('{"componentName":"Page"');
+if (state === RepairJsonState.SUCCESS || state === RepairJsonState.REPAIRED) {
+ console.log(value);
+}
+```
+
+### buildMaterialDefaultValueMap()
+
+Builds a component → default props map from materials metadata for Renderer default-prop merging.
+
+- **Type**
+
+```typescript
+function buildMaterialDefaultValueMap(
+ materialsMeta?: Partial,
+): MaterialDefaultValueMap
+```
+
+- **Parameters**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `materialsMeta` | `Partial` | No | Materials metadata, see [`IMaterialsMeta`](#imaterialsmeta); omitted yields an empty map |
+
+- **Returns**: [`MaterialDefaultValueMap`](#materialdefaultvaluemap)
+
+## Types
+
+### CardSchema
+
+```typescript
+interface JSExpression {
+ type: 'JSExpression';
+ value: string;
+ model?: boolean;
+}
+
+interface JSFunction {
+ type: 'JSFunction';
+ value: string;
+ params?: string[];
+}
+
+type Methods = Record;
+
+interface LifeCycles {
+ onMounted?: JSFunction;
+ onUnmounted?: JSFunction;
+}
+
+interface Node {
+ id?: string;
+ componentName: string;
+ props?: Record;
+ children?: Node[] | string;
+ componentType?: 'Block' | 'PageStart' | 'PageSection';
+ slot?: string | Record;
+ params?: string[];
+ loop?: Record;
+ loopArgs?: string[];
+ condition?: boolean | Record;
+}
+
+type RootNode = Omit & {
+ css?: string;
+ state?: Record;
+ methods?: Methods;
+ lifeCycles?: LifeCycles;
+};
+
+type CardSchema = RootNode;
+type NodeSchema = Node;
+```
+
+### IChatMessage
+
+```typescript
+interface IStreamDelta {
+ reasoning_content?: string | null;
+ content?: string | null;
+ tool_calls?: any;
+ tool_calls_result?: any;
+}
+
+type IMessageItem =
+ | { type: 'schema-card'; content: any; id?: string; state?: Record }
+ | { type: 'markdown'; content: string }
+ | { type: 'reasoning'; content: string; thinking?: boolean }
+ | { type: 'tool'; name: string; status: string; content?: any; [key: string]: any }
+ | { type: string; content: any; [customKey: string]: any };
+
+interface IChatMessage {
+ role: 'assistant';
+ content: string;
+ messages: IMessageItem[];
+ [key: string]: any;
+}
+```
+
+### IMaterials
+
+```typescript
+interface IMaterials {
+ components?: Record; // component name → runtime component
+ requiredCompleteFieldSelectors?: string[]; // buffer-field selectors
+ defaultPropsMap?: Record; // default props map
+ [key: string]: any;
+}
+```
+
+### IMaterialsMeta
+
+```typescript
+interface IExample {
+ id?: string;
+ name: string;
+ description?: string;
+ schema: CardSchema;
+}
+
+interface IMaterialsMeta {
+ materials: IMaterialsProtocol[]; // materials protocol payload
+ examples: IExample[]; // prompt examples
+ whiteList: string[]; // component whitelist
+ wrapperComponent?: string; // wrapper component name, e.g. TinyCard
+ rules?: string[]; // materials-side generation rules
+}
+```
+
+### MaterialDefaultValueMap
+
+```typescript
+type MaterialDefaultValueMap = Record>; // component name → prop defaults
+```
+
+### IGenPromptFramework
+
+```typescript
+type IGenPromptFramework = 'Vue' | 'React' | 'Angular' | string;
+```
+
+### IGenPromptFrameworkConfig
+
+```typescript
+interface IGenPromptFrameworkConfig {
+ rules?: string[]; // framework default generation rules
+}
+```
+
+### IGenPromptCustomConfig
+
+```typescript
+interface IGenPromptCustomConfig {
+ customComponents?: IGenPromptComponent[]; // custom component descriptions
+ customSnippets?: IGenPromptSnippet[]; // custom snippets
+ customExamples?: IGenPromptExample[]; // custom examples
+ customActions?: IGenPromptAction[]; // custom actions
+}
+
+interface IGenPromptAction {
+ name: string;
+ description?: string;
+ parameters?: JSONSchema;
+ return?: JSONSchema; // return-value JSON Schema (optional)
+ async?: boolean; // whether the action is async, default false
+}
+```
+
+### IGenPromptOptions
+
+```typescript
+interface IGenPromptOptions {
+ isSkill?: boolean; // Skill-mode prefix and rules, default false
+ includeJsonSchema?: boolean; // include JSON Schema section, default true
+ includeSnippets?: boolean; // include Snippets section, default true
+ includeExamples?: boolean; // include Examples section, default true
+ includeActions?: boolean; // include Actions section, default true
+ includeAboutThis?: boolean; // include About This section, default true
+ includeBaseRules?: boolean; // include base rules, default true
+ rules?: string[]; // extra rules merged with materials and framework defaults
+}
+```
+
+### IPatchOptions
+
+```typescript
+interface IPatchOptions {
+ requiredCompleteFieldSelectors?: string[]; // buffer-field selectors
+}
+```
+
+### RepairJsonState
+
+```typescript
+enum RepairJsonState {
+ INVALID_INPUT = 'invalid-input', // invalid input
+ SUCCESS = 'success-parse', // parsed successfully
+ REPAIRED = 'repaired-parse', // parsed after repair
+ FAILED = 'failed-repair', // repair failed
+}
+```
diff --git a/docs/src/en/components/materials/angular-opentiny-ng.md b/docs/src/en/components/materials/angular-opentiny-ng.md
new file mode 100644
index 00000000..08cf6d56
--- /dev/null
+++ b/docs/src/en/components/materials/angular-opentiny-ng.md
@@ -0,0 +1,40 @@
+# Angular OpenTiny NG
+
+`@opentiny/genui-sdk-materials-angular-opentiny-ng` is a materials package based on [OpenTiny NG](https://opentiny.design/tiny-ng/), providing a runtime component map and prompt metadata.
+
+See [Core - IMaterials](../core/api#imaterials) / [IMaterialsMeta](../core/api#imaterialsmeta) for types.
+
+## Exports
+
+| Entry | Exports |
+|-------|---------|
+| `.` | `materials`, `materialsMeta` |
+| `./materials` | `materials` |
+| `./meta` | `materialsMeta` |
+
+## materials
+
+- **Type**: `IMaterials`
+- **Description**: OpenTiny NG component map for ConfigProvider.
+
+```typescript
+import { materials } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/materials';
+```
+
+```html
+
+
+
+```
+
+## materialsMeta
+
+- **Type**: `IMaterialsMeta`
+- **Description**: For server-side [`genPrompt`](../core/api#genprompt). `wrapperComponent` defaults to `TiCard`.
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/meta';
+
+const systemPrompt = genPrompt('Angular', materialsMeta);
+```
diff --git a/docs/src/en/components/materials/vue-element-plus.md b/docs/src/en/components/materials/vue-element-plus.md
new file mode 100644
index 00000000..ab8c755a
--- /dev/null
+++ b/docs/src/en/components/materials/vue-element-plus.md
@@ -0,0 +1,42 @@
+# Vue Element Plus
+
+`@opentiny/genui-sdk-materials-vue-element-plus` is a materials package based on [Element Plus](https://element-plus.org/), providing a runtime component map and prompt metadata.
+
+See [Core - IMaterials](../core/api#imaterials) / [IMaterialsMeta](../core/api#imaterialsmeta) for types.
+
+## Exports
+
+| Entry | Exports |
+|-------|---------|
+| `.` | `materials`, `materialsMeta` |
+| `./materials` | `materials` |
+| `./meta` | `materialsMeta` |
+
+## materials
+
+- **Type**: `IMaterials`
+- **Description**: Element Plus component map for [GenuiConfigProvider](../config-provider#materials).
+
+```typescript
+import 'element-plus/dist/index.css';
+import { materials } from '@opentiny/genui-sdk-materials-vue-element-plus/materials';
+import { GenuiChat, GenuiConfigProvider } from '@opentiny/genui-sdk-vue';
+```
+
+```vue
+
+
+
+```
+
+## materialsMeta
+
+- **Type**: `IMaterialsMeta`
+- **Description**: For server-side [`genPrompt`](../core/api#genprompt). `wrapperComponent` defaults to `ElCard`.
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-element-plus/meta';
+
+const systemPrompt = genPrompt('Vue', materialsMeta);
+```
diff --git a/docs/src/en/components/materials/vue-opentiny-vue.md b/docs/src/en/components/materials/vue-opentiny-vue.md
new file mode 100644
index 00000000..06dd2671
--- /dev/null
+++ b/docs/src/en/components/materials/vue-opentiny-vue.md
@@ -0,0 +1,41 @@
+# Vue OpenTiny Vue
+
+`@opentiny/genui-sdk-materials-vue-opentiny-vue` is a materials package based on [OpenTiny Vue](https://opentiny.design/tiny-vue/), providing a runtime component map and prompt metadata.
+
+See [Core - IMaterials](../core/api#imaterials) / [IMaterialsMeta](../core/api#imaterialsmeta) for types.
+
+## Exports
+
+| Entry | Exports |
+|-------|---------|
+| `.` | `materials`, `miniMaterials`, `materialsMeta`, `miniMaterialsMeta` |
+| `./materials` | `materials`, `miniMaterials` |
+| `./meta` | `materialsMeta`, `miniMaterialsMeta` |
+
+## materials / miniMaterials
+
+- **Type**: `IMaterials`
+- **Description**: OpenTiny Vue component map for [GenuiConfigProvider](../config-provider#materials). `miniMaterials` is a smaller set (without charts, etc.).
+
+```typescript
+import { materials } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/materials';
+import { GenuiChat, GenuiConfigProvider } from '@opentiny/genui-sdk-vue';
+```
+
+```vue
+
+
+
+```
+
+## materialsMeta / miniMaterialsMeta
+
+- **Type**: `IMaterialsMeta`
+- **Description**: For server-side [`genPrompt`](../core/api#genprompt). `wrapperComponent` defaults to `TinyCard`. `miniMaterialsMeta` pairs with the mini whitelist and examples.
+
+```typescript
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/meta';
+
+const systemPrompt = genPrompt('Vue', materialsMeta);
+```
diff --git a/docs/src/en/components/renderer.md b/docs/src/en/components/renderer.md
new file mode 100644
index 00000000..f1321d96
--- /dev/null
+++ b/docs/src/en/components/renderer.md
@@ -0,0 +1,283 @@
+# GenuiRenderer Component
+
+`GenuiRenderer` is the core rendering component (Renderer) of GenUI SDK. It renders structured JSON Schema returned by large language models into interactive UI.
+
+When using only Renderer, you can import it on demand from `@opentiny/genui-sdk-vue/renderer`. See [Quick Start - Subpath Imports](../guide/quick-start#subpath-imports).
+
+## Compatibility Component: GenuiLegacyRenderer
+
+::: warning Materials configuration (since v1.3.0)
+`GenuiRenderer` has been refactored to decouple materials. The component no longer includes any UI materials; inject them via `GenuiConfigProvider`.
+
+For previous behavior, use `GenuiLegacyRenderer` (`@opentiny/genui-sdk-vue/legacy-renderer`) instead.
+:::
+
+`GenuiLegacyRenderer` bundles OpenTiny default materials. Use it when migrating old projects that did not configure `GenuiConfigProvider`.
+
+```vue
+
+
+
+
+
+```
+
+## Props
+
+### content
+
+- **Type**: `string | object`
+- **Required**: Yes
+- **Description**: Schema content as a string or object. When a string is passed, the component attempts to parse "partial JSON" and auto-complete it, supporting streaming updates.
+
+```vue
+
+
+
+
+
+```
+
+### isJsonComplete
+
+- **Type**: `boolean`
+- **Required**: No
+- **Description**: Applies only when `content` is a JSON object. Marks whether the current JSON is complete, helping the buffer logic determine whether values are complete.
+
+```vue
+
+
+
+
+
+```
+
+### generating
+
+- **Type**: `boolean`
+- **Required**: No
+- **Description**: Indicates whether the current conversation is still generating. Used to control UI loading state.
+
+```vue
+
+
+
+
+
+```
+
+### customComponents
+
+- **Type**: `Record`
+- **Required**: No
+- **Description**: Custom component map for extending the available component list.
+
+```vue
+
+
+
+
+
+```
+
+See [Renderer - Custom Components](../examples/renderer/custom-components) for detailed usage.
+
+### customActions
+
+- **Type**: `Record void }>`
+- **Required**: No
+- **Description**: Custom action map defining actions that can be invoked from components.
+
+```vue
+
+
+
+
+
+```
+
+See [Renderer - Custom Actions](../examples/renderer/custom-actions) for detailed usage.
+
+### requiredCompleteFieldSelectors
+
+- **Type**: `string[]`
+- **Required**: No
+- **Description**: Specifies which field paths must be complete before updates are applied. Used to control buffering strategy during streaming updates.
+
+```vue
+
+
+
+
+```
+
+See [Renderer - Buffer Field Configuration](../examples/renderer/required-complete-field-selectors) for detailed usage.
+
+### state
+
+- **Type**: `Record`
+- **Required**: No
+- **Description**: Global state passed to the renderer, accessible in components via context.
+
+```vue
+
+
+
+```
+
+See [Renderer - Passing and Merging State](../examples/renderer/state) for detailed usage.
+
+## Slots
+
+### header
+
+- **Parameters**: `{ schema: CardSchema, isError: boolean, isFinished: boolean }`
+- **Description**: Custom renderer header content
+
+```vue
+
+
+
+
+
+
+
+```
+
+### footer
+
+- **Parameters**: `{ schema: CardSchema, isError: boolean, isFinished: boolean }`
+- **Description**: Custom renderer footer content
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Types
+
+### CardSchema
+
+```typescript
+type CardSchema = {
+ id?: string; // Optional root node id
+ methods?: Methods; // Method collection
+ state?: Record; // Global state; required for two-way form binding
+ componentName: string; // Root component name, usually Page
+ props?: Record; // Root component props
+ componentType?: 'Block' | 'PageStart' | 'PageSection'; // Node type, usually omitted
+ children?: NodeSchema[]; // Root child nodes
+ slot?: string | JSSlot | Record; // Root slot content
+ loop?: Record; // Root loop render config
+ loopArgs?: string[]; // Root loop argument names
+ condition?: boolean | Record; // Root conditional render config
+ css?: string; // Global CSS string
+};
+
+type NodeSchema = {
+ id?: string; // Unique node id
+ componentName: string; // Component name
+ props?: Record; // Component props
+ children?: NodeSchema[] | string; // Child nodes or string (recursive)
+ componentType?: 'Block' | 'PageStart' | 'PageSection'; // Node type, usually omitted
+ slot?: string | JSSlot | Record; // Slot content
+ params?: string[]; // Parameter names
+ loop?: Record; // Loop render config
+ loopArgs?: string[]; // Loop argument names
+ condition?: boolean | Record; // Conditional render config
+};
+
+type PropValue =
+ | string // String
+ | number // Number
+ | boolean // Boolean
+ | null // null
+ | JSExpression // JS expression wrapper
+ | JSFunction // JS function wrapper
+ | JSSlot // Slot wrapper
+ | PropValue[] // Recursive array
+ | Record; // Recursive object
+
+type JSExpression = { type: 'JSExpression'; value: string; model?: boolean };
+type JSFunction = { type: 'JSFunction'; value: string; params?: string[] };
+type JSSlot = { type: 'JSSlot'; value: string | Record };
+```
+
+### IRendererProps
+
+```typescript
+interface IRendererProps {
+ content: string | { [prop: string]: any };
+ isJsonComplete?: boolean;
+ generating?: boolean;
+ customComponents?: Record;
+ customActions?: Record<
+ string,
+ {
+ execute: (params: any, context: any) => void;
+ }
+ >;
+ requiredCompleteFieldSelectors?: string[];
+ id?: string;
+ state?: Record;
+}
+```
diff --git a/docs/src/en/components/server/api.md b/docs/src/en/components/server/api.md
new file mode 100644
index 00000000..e36ba432
--- /dev/null
+++ b/docs/src/en/components/server/api.md
@@ -0,0 +1,134 @@
+# API Reference
+
+`@opentiny/genui-sdk-server` provides component APIs for building large language model chat HTTP services.
+
+## startServer()
+
+Starts an Express HTTP server that provides chat completion services.
+
+- **Type**
+
+```typescript
+function startServer(options: IStartServerOptions): void
+
+interface IStartServerOptions {
+ /** API base URL */
+ baseURL: string;
+ /** API key */
+ apiKey: string;
+ /** Server port, default 3100 */
+ port?: number;
+ /** Max attempts when port is in use, default 10 */
+ maxAttempts?: number;
+}
+```
+
+- **Details**
+
+Creates an Express app with CORS enabled and registers the chat route (`/chat/completions`). If the specified port is in use, it automatically tries the next port (up to `maxAttempts` times). On success, the server address is printed to the console.
+
+- **Example**
+
+```typescript
+import { startServer } from '@opentiny/genui-sdk-server';
+
+startServer({
+ port: 3100,
+ baseURL: 'https://api.openai.com/v1',
+ apiKey: '',
+ maxAttempts: 10,
+});
+```
+
+## equipChatCompletions()
+
+Equips an Express app with chat completion functionality by registering the route handler.
+
+- **Type**
+
+```typescript
+function equipChatCompletions(
+ app: Express,
+ options: IEquipChatCompletionsOptions
+): void
+
+interface IEquipChatCompletionsOptions {
+ /** Route path, e.g. '/chat/completions' */
+ route: string;
+ /** API key */
+ apiKey: string;
+ /** API base URL */
+ baseURL: string;
+}
+```
+
+- **Details**
+
+Creates a chat completion request instance, builds a request handler, and registers it on the specified route (POST).
+
+- **Example**
+
+```typescript
+import express from 'express';
+import { equipChatCompletions } from '@opentiny/genui-sdk-server';
+
+const app = express();
+
+equipChatCompletions(app, {
+ route: '/chat/completions',
+ apiKey: '',
+ baseURL: 'https://api.openai.com/v1',
+});
+
+app.listen(3000);
+```
+
+## createChatCompletionHandler()
+
+Creates a chat completion request handler that processes HTTP requests and returns streaming responses.
+
+- **Type**
+
+```typescript
+function createChatCompletionHandler(
+ config: IChatCompletionHandlerConfig
+): { handler: (req: IncomingMessage, res: ServerResponse) => Promise }
+
+interface IChatCompletionHandlerConfig {
+ chatCompletions: (
+ params: ChatCompletionCreateParamsBase,
+ options?: IRequestOptions
+ ) => Promise;
+}
+
+interface IRequestOptions {
+ signal?: AbortSignal | undefined | null;
+}
+```
+
+- **Details**
+
+Parses the request body (JSON), calls the chat completion API for a streaming response, converts the stream to SSE (Server-Sent Events), handles client disconnects (automatically aborting the request), and provides unified error handling and formatting.
+
+If the response is not streaming, an error is thrown. All errors are caught and formatted into a unified error response. If response headers have already been sent, errors are appended to the stream in SSE format.
+
+- **Example**
+
+```typescript
+import { createChatCompletionHandler } from '@opentiny/genui-sdk-server';
+import { FetchChatCompletions } from '@opentiny/genui-sdk-chat-completions';
+import http from 'http';
+
+const chatCompletion = new FetchChatCompletions({
+ apiKey: '',
+ baseURL: 'https://api.openai.com/v1',
+});
+
+const { handler } = createChatCompletionHandler({
+ chatCompletions: (params, options) =>
+ chatCompletion.chatStream(params, options),
+});
+
+const server = http.createServer(handler);
+server.listen(3000);
+```
diff --git a/docs/src/en/components/server/cli.md b/docs/src/en/components/server/cli.md
new file mode 100644
index 00000000..4c65f114
--- /dev/null
+++ b/docs/src/en/components/server/cli.md
@@ -0,0 +1,147 @@
+# CLI
+
+`genui-sdk-server` is a globally installed command-line tool for quickly starting a GenUI SDK chat completion HTTP service. It provides zero-config server startup with automatic environment variable loading and port conflict detection.
+
+## Installation
+
+Install globally via npm or yarn:
+
+```bash
+npm install -g @opentiny/genui-sdk-server
+# or
+yarn global add @opentiny/genui-sdk-server
+```
+
+After installation, you can use the `genui-sdk-server` command in your terminal.
+
+## Quick Start
+
+1. Create a `.env` file and configure required environment variables:
+
+```env
+BASE_URL=https://api.openai.com/v1
+API_KEY=
+PORT=3100
+```
+
+2. Run the command to start the service:
+
+```bash
+genui-sdk-server
+```
+
+On success, the server address is printed, for example:
+
+```text
+genui-sdk-server is running on http://localhost:3100
+```
+
+## Commands
+
+### genui-sdk-server
+
+Starts the GenUI SDK chat HTTP service.
+
+#### Usage
+
+```bash
+genui-sdk-server [options]
+```
+
+#### Options
+
+| Option | Short | Type | Description |
+|:---|:---:|:---:|:---|
+| `--envFile ` | `-e` | `string` | Custom environment file path (default: `.env` in the current directory) |
+| `--port ` | `-p` | `number` | Server port (default: 3100 or `PORT` environment variable) |
+| `--help` | `-h` | - | Show help information |
+
+#### Environment Variables
+
+The CLI requires the following environment variables (via `.env` file or system environment):
+
+| Variable | Required | Description | Default |
+|:---|:---:|:---|:---|
+| `BASE_URL` | Yes | API base URL, e.g. `https://api.openai.com/v1` | - |
+| `API_KEY` | Yes | API key | - |
+| `PORT` | No | Server port | `3100` |
+
+**Environment variable priority**:
+
+1. Command-line option `--port` (highest priority)
+2. Environment variable `PORT`
+3. Default value `3100`
+
+#### Features
+
+- **Automatic port detection**: If the specified port is in use, tries the next port automatically (up to 10 attempts)
+- **Environment variable loading**: Supports loading configuration from `.env` files or system environment variables
+- **CORS support**: CORS is enabled automatically for cross-origin requests
+- **Streaming responses**: Supports SSE (Server-Sent Events) streaming format
+
+#### Examples
+
+**Basic usage**
+
+Start with default configuration (reads `.env` in the current directory, port 3100):
+
+```bash
+genui-sdk-server
+```
+
+**Custom environment file**
+
+Use a custom environment file:
+
+```bash
+genui-sdk-server -e /path/to/custom/.env
+```
+
+**Specify port**
+
+Set the server port via command-line option:
+
+```bash
+genui-sdk-server -p 3000
+```
+
+**Combined usage**
+
+Specify both environment file and port:
+
+```bash
+genui-sdk-server -e /path/to/.env -p 3000
+```
+
+**System environment variables**
+
+Use system environment variables without a `.env` file:
+
+```bash
+# Set system environment variables
+export BASE_URL=https://api.openai.com/v1
+export API_KEY=
+export PORT=3000
+
+# Start the service
+genui-sdk-server
+```
+
+**Show help**
+
+```bash
+genui-sdk-server --help
+# or
+genui-sdk-server -h
+```
+
+## Server Endpoints
+
+After startup, the service exposes the following endpoint:
+
+- **POST** `/chat/completions` - Chat completion endpoint with streaming response (SSE format)
+
+## Related Links
+
+- [Server API](./api) - Component API documentation
+- [Usage Guide](../../guide/server-usage) - Detailed usage guide
diff --git a/docs/src/en/examples/angular/renderer/custom-actions.md b/docs/src/en/examples/angular/renderer/custom-actions.md
new file mode 100644
index 00000000..852e0761
--- /dev/null
+++ b/docs/src/en/examples/angular/renderer/custom-actions.md
@@ -0,0 +1,62 @@
+# Renderer - Custom Actions
+
+Custom actions let you implement complex interaction logic. Pair them with prompts so the LLM emits schema JSON that invokes those actions.
+
+## Passing customActions to the Renderer
+
+Pass actions via the `customActions` prop. Each action includes:
+
+- `name`: Action name
+- `description`: Action description
+- `execute`: Handler receiving `params` and `context`
+- `parameters`: Optional parameter schema; the model uses it to fill `params` for `execute`
+
+### execute Parameters
+
+- `params`: Arguments passed when the action is invoked
+- `context`: Renderer context (state and methods); use `context.state` for two-way bound global state
+
+### Example: Open a Page
+
+
+
+## Send Custom Actions to the Server
+
+After registering actions on the renderer, include them in chat requests so the model can generate correct action calls.
+
+```ts {9-31}
+const response = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ messages: [{ role: 'user', content: userInput }],
+ model: 'deepseek-v3.2',
+ stream: true,
+ metadata: {
+ tinygenui: JSON.stringify({
+ framework: 'Angular',
+ customActions: [
+ {
+ name: 'openPage',
+ description: 'Open a page',
+ parameters: {
+ type: 'object',
+ properties: {
+ url: {
+ type: 'string',
+ description: 'URL to open',
+ },
+ target: {
+ type: 'string',
+ description: 'Target window: _self (same tab) or _blank (new tab)',
+ },
+ },
+ required: ['url', 'target'],
+ },
+ }
+ ]
+ }),
+ },
+ }),
+});
+```
diff --git a/docs/src/en/examples/angular/renderer/required-complete-field-selectors.md b/docs/src/en/examples/angular/renderer/required-complete-field-selectors.md
new file mode 100644
index 00000000..ccf42a3b
--- /dev/null
+++ b/docs/src/en/examples/angular/renderer/required-complete-field-selectors.md
@@ -0,0 +1,13 @@
+# Renderer - Buffered Fields
+
+See [Configure Buffered Fields](../../renderer/required-complete-field-selectors).
+
+## Custom Configuration
+
+### Example
+
+
+
+### Behavior
+
+Before configuring `requiredCompleteFieldSelectors`, `Text` content updates as the model streams partial output. After configuration, the full text is shown only when complete; text inside nested `div` elements is not affected.
diff --git a/docs/src/en/examples/angular/renderer/state.md b/docs/src/en/examples/angular/renderer/state.md
new file mode 100644
index 00000000..bead2151
--- /dev/null
+++ b/docs/src/en/examples/angular/renderer/state.md
@@ -0,0 +1,62 @@
+# Renderer - Passing and Merging State
+
+Use `state` to pass initial state to the renderer. It is merged into global state on init and accessible from component context.
+
+## Passing State to the Component
+
+State is merged when the component initializes and **does not update dynamically**.
+
+### Use Case
+
+`state` is mainly for **restoring history**: pass saved state from a past conversation so the renderer can rehydrate.
+
+### Basic Usage
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
+
+@Component({
+ imports: [GenuiRenderer],
+ template: `
+
+ `,
+})
+export class GenuiExample {
+ generating = false;
+ content = {};
+
+ // State restored from history
+ savedState = {
+ formData: {
+ name: 'John Doe',
+ age: 30,
+ },
+ };
+}
+```
+
+### Accessing State in Actions
+
+In custom actions, use `context.state`:
+
+```ts
+const customActions = {
+ getState: {
+ execute: (params: any, context: Record) => {
+ const state = context.state;
+ alert(`Global state: ${JSON.stringify(state)}`);
+ },
+ },
+};
+```
+
+#### Full Example
+
+
+
+## Notes
+
+1. **Init-only merge**: State is merged only on init; later updates are ignored.
+2. **History replay**: Intended for restoring saved conversation state.
+3. **Serializable data**: Avoid functions, DOM nodes, and other non-serializable values.
diff --git a/docs/src/en/examples/chat/custom-actions.md b/docs/src/en/examples/chat/custom-actions.md
new file mode 100644
index 00000000..7f2efe48
--- /dev/null
+++ b/docs/src/en/examples/chat/custom-actions.md
@@ -0,0 +1,92 @@
+# Chat Component - Custom Actions
+
+In the `GenuiChat` component, a built-in continue-chat Action `continueChat` is included. You can pass custom Actions via the `customActions` prop so the AI can invoke them from generated UI.
+
+## Basic Usage
+
+```vue {14-36}
+
+
+
+
+
+
+
+```
+
+## Action Definition Format
+
+Each Action must include the following fields:
+
+- `name`: Action name, invoked in Schema via `this.callAction(name, params)`
+- `description`: Action description to help the AI understand when to use it
+- `parameters`: Parameter definition as JSON Schema
+- `execute`: Execution function (optional, used for frontend implementation)
+
+```typescript
+interface CustomAction {
+ name: string;
+ description: string;
+ parameters: JSONSchema;
+ execute?: (params: any) => void; // frontend implementation
+}
+```
+
+## Invoking Actions in Schema
+
+AI-generated Schema can invoke these Actions via `JSFunction`:
+
+```json
+{
+ "componentName": "TinyButton",
+ "props": {
+ "children": "Open New Page",
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { this.callAction('openPage', { url: 'https://example.com', target: '_blank' }); }"
+ }
+ }
+}
+```
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/chat/custom-components.md b/docs/src/en/examples/chat/custom-components.md
new file mode 100644
index 00000000..d2aaf637
--- /dev/null
+++ b/docs/src/en/examples/chat/custom-components.md
@@ -0,0 +1,92 @@
+# Chat Component - Custom Components
+
+In the `GenuiChat` component, you can pass custom components via the `customComponents` prop to extend the component library available to the LLM.
+
+## Basic Usage
+
+```vue { 16-43 }
+
+
+
+
+
+
+
+```
+
+## Example schemaJson returned by the LLM
+
+```json
+{
+ "type": "schema-card",
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "Custom Component Example",
+ "style": "font-size: 20px; font-weight: bold; margin-bottom: 16px;"
+ }
+ },
+ {
+ "componentName": "UserProfile",
+ "props": {
+ "name": "John Doe",
+ "email": "john@example.com",
+ "avatar": "/genui-sdk-docs/logo.svg"
+ }
+ }
+ ]
+}
+```
+
+When the AI generates a schema, ensure `componentName` matches the component name registered in `customComponents`, and pass `props` according to the fields defined in `schema`.
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/chat/custom-examples.md b/docs/src/en/examples/chat/custom-examples.md
new file mode 100644
index 00000000..b18b31d0
--- /dev/null
+++ b/docs/src/en/examples/chat/custom-examples.md
@@ -0,0 +1,211 @@
+# Chat Component - Custom Examples
+
+Custom Examples provide component usage samples to help the LLM learn how to compose more polished and rich UI. Use them together with prompts so the LLM outputs the corresponding schemaJson to apply these examples.
+
+## Example Definition Format
+
+Each Example must include the following fields:
+
+```typescript
+interface IGenPromptExample {
+ name: string;
+ description?: string;
+ schema: CardSchema;
+}
+```
+
+- `name`: Example name
+- `description`: Example description to help the LLM understand the purpose
+- `schema`: Component schema example demonstrating usage
+
+## Developer Profile Card Example
+
+The following example shows how to use the TinyCard component to create a developer profile card with a vibrant gradient background:
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/chat/custom-fetch.md b/docs/src/en/examples/chat/custom-fetch.md
new file mode 100644
index 00000000..f2b3f876
--- /dev/null
+++ b/docs/src/en/examples/chat/custom-fetch.md
@@ -0,0 +1,404 @@
+# Chat Component - Custom Fetch
+
+The `GenuiChat` component supports a custom fetch function, allowing you to fully customize HTTP request behavior. This is useful for integrating third-party SDKs, adding authentication, handling tool calls, implementing custom streaming responses, and more.
+
+## Parameters
+
+- `url`: Request URL
+- `options.method`: HTTP method (usually `'POST'`)
+- `options.headers`: Request headers object
+- `options.body`: Request body (JSON string) containing `messages`, `model`, `temperature`, and `metadata` (with processed `customComponents`, `customSnippets`, `customExamples`, and `customActions` information)
+- `options.signal`: AbortSignal used to cancel the request
+
+## Return Value
+
+Must return a `Response` object or `Promise`. The response should follow the OpenAI-compatible streaming format (SSE), or return a standard JSON response.
+
+## Use Cases
+
+### Adding Authentication Headers
+
+Pass a custom fetch function via the `customFetch` prop:
+
+```vue
+
+
+
+
+
+
+
+```
+
+### Handling Tool Calls and Multi-turn Conversations
+
+Use `customFetch` to implement tool calling (Function Calling) and multi-turn conversations. The following complete example demonstrates how to do this.
+
+#### 1. Define Tools
+
+First, define the available tools. Each tool has two parts: `definition` (tool definition in OpenAI tool format) and `execute` (execution function).
+
+```typescript
+import OpenAI from 'openai';
+
+/**
+ * Tool to add two numbers
+ */
+export const addTwoNumbersTool = {
+ definition: {
+ type: 'function' as const,
+ function: {
+ name: 'add_two_numbers',
+ description:
+ 'Adds two numbers. This is a math tool for summing two numbers. You must provide parameters a and b. Example: if a=5, b=3, returns 8.',
+ parameters: {
+ type: 'object',
+ properties: {
+ a: {
+ type: 'number',
+ description: 'First number to add. Required. Must be a number. Example: 5',
+ },
+ b: {
+ type: 'number',
+ description: 'Second number to add. Required. Must be a number. Example: 3',
+ },
+ },
+ required: ['a', 'b'],
+ },
+ },
+ },
+ execute: async ({ a, b }: { a: number; b: number }) => {
+ return a + b;
+ },
+};
+
+/**
+ * List of all available tools
+ */
+export const availableTools: Record<
+ string,
+ {
+ definition: OpenAI.Chat.Completions.ChatCompletionTool;
+ execute: (args: any) => Promise | any;
+ }
+> = {
+ add_two_numbers: addTwoNumbersTool,
+};
+```
+
+#### 2. Implement CustomFetch for Tool Calls
+
+Next, implement the `customFetch` function to handle tool calls and multi-turn conversations:
+
+```typescript
+import OpenAI from 'openai';
+import type { CustomFetch } from '@opentiny/genui-sdk-vue';
+import { availableTools } from './tools';
+
+/**
+ * OpenAI SDK configuration
+ */
+export interface OpenAIConfig {
+ apiKey: string;
+ baseURL?: string;
+ organization?: string;
+}
+
+/**
+ * Execute a tool call
+ */
+async function executeToolCall(toolName: string, args: any): Promise {
+ const tool = availableTools[toolName];
+ if (!tool) {
+ throw new Error(`Tool ${toolName} not found`);
+ }
+
+ try {
+ const result = await tool.execute(args);
+ return typeof result === 'string' ? result : JSON.stringify(result);
+ } catch (error) {
+ return JSON.stringify({
+ error: error instanceof Error ? error.message : 'Unknown error',
+ });
+ }
+}
+
+/**
+ * Accumulate tool call data
+ * Accumulates incremental tool call deltas from streaming into complete tool call objects
+ */
+function accumulateToolCalls(toolCalls: any[], toolCallDeltas: any[]): void {
+ for (const delta of toolCallDeltas) {
+ const index = delta.index ?? 0;
+ const toolCall = (toolCalls[index] ??= {
+ id: delta.id ?? '',
+ type: 'function',
+ function: { name: '', arguments: '' },
+ });
+ if (delta.id) toolCall.id = delta.id;
+ if (delta.function?.name) toolCall.function.name += delta.function.name;
+ if (delta.function?.arguments) toolCall.function.arguments += delta.function.arguments;
+ }
+}
+
+/**
+ * Execute a single tool call and return the result
+ */
+async function executeSingleToolCall(toolCall: any, currentMessages: any[]): Promise {
+ const createResult = (result: string) => {
+ currentMessages.push({ role: 'tool', tool_call_id: toolCall.id, content: result });
+ return {
+ id: toolCall.id,
+ type: 'function',
+ function: { name: toolCall.function.name, arguments: toolCall.function.arguments, result },
+ };
+ };
+ try {
+ const args = JSON.parse(toolCall.function.arguments);
+ const result = await executeToolCall(toolCall.function.name, args);
+ return createResult(result);
+ } catch (error) {
+ return createResult(JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error' }));
+ }
+}
+
+/**
+ * Create a customRequest function using the OpenAI SDK (handles tool calls and multi-turn conversations)
+ *
+ * @param config OpenAI configuration
+ * @returns CustomFetch function
+ */
+export function createOpenAICustomFetch(config: OpenAIConfig): CustomFetch {
+ return async (
+ url: string,
+ options: {
+ method: string;
+ headers: Record;
+ body: string;
+ signal?: AbortSignal;
+ },
+ ): Promise => {
+ // Parse request body
+ const requestBody = JSON.parse(options.body);
+ const { messages, model, temperature } = requestBody;
+
+ try {
+ const openai = new OpenAI({
+ apiKey: config.apiKey,
+ baseURL: config.baseURL,
+ dangerouslyAllowBrowser: true,
+ });
+
+ const tools = Object.values(availableTools).map((tool) => tool.definition);
+ const maxSteps = 20; // Maximum number of tool call steps
+
+ // Convert stream to SSE-format Response
+ const encoder = new TextEncoder();
+ const readableStream = new ReadableStream({
+ async start(controller) {
+ try {
+ let currentMessages = [...messages];
+ let stepCount = 0;
+
+ while (stepCount < maxSteps) {
+ // Create streaming request
+ const stream = await openai.chat.completions.create(
+ {
+ model,
+ messages: currentMessages,
+ temperature,
+ tools: tools.length > 0 ? tools : undefined,
+ tool_choice: tools.length > 0 ? 'auto' : undefined,
+ stream: true,
+ },
+ {
+ signal: options.signal,
+ },
+ );
+
+ let toolCalls: any[] = [];
+ let hasToolCalls = false;
+
+ // Process streaming response
+ for await (const chunk of stream) {
+ const choice = chunk.choices?.[0];
+ if (!choice) continue;
+
+ const delta = choice.delta;
+
+ // Accumulate tool call data
+ if (delta.tool_calls) {
+ hasToolCalls = true;
+ accumulateToolCalls(toolCalls, delta.tool_calls);
+ }
+
+ // Pass through original chunk
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
+
+ // Handle finish reason
+ if (choice.finish_reason === 'tool_calls' && toolCalls.length > 0) {
+ // Execute tool calls
+ currentMessages.push({ role: 'assistant', content: null, tool_calls: toolCalls });
+ const toolResults = await Promise.all(
+ toolCalls.map((toolCall, i) =>
+ executeSingleToolCall(toolCall, currentMessages).then((result) => ({ ...result, index: i })),
+ ),
+ );
+
+ // Send tool call results
+ if (toolResults.length > 0) {
+ const toolResultChunk = {
+ id: chunk.id,
+ object: 'chat.completion.chunk',
+ model: chunk.model || model,
+ created: chunk.created || Math.floor(Date.now() / 1000),
+ choices: [{ index: 0, delta: { tool_calls_result: toolResults }, finish_reason: 'tool_calls' }],
+ };
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(toolResultChunk)}\n\n`));
+ }
+
+ stepCount++;
+ break;
+ }
+
+ if (choice.finish_reason) {
+ // Normal completion, exit outer loop
+ break;
+ }
+ }
+
+ // Exit loop if there are no tool calls
+ if (!hasToolCalls) {
+ break;
+ }
+ }
+
+ // Send end marker
+ controller.enqueue(encoder.encode('data: [DONE]\n\n'));
+ controller.close();
+ } catch (error) {
+ const errorData = {
+ error: {
+ message: error instanceof Error ? error.message : 'Unknown error',
+ type: 'stream_error',
+ },
+ };
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorData)}\n\n`));
+ controller.error(error);
+ }
+ },
+ });
+
+ return new Response(readableStream, {
+ headers: {
+ 'Content-Type': 'text/event-stream',
+ 'Cache-Control': 'no-cache',
+ 'Connection': 'keep-alive',
+ },
+ status: 200,
+ });
+ } catch (error: any) {
+ console.error('[OpenAI SDK Error]', {
+ url,
+ error: error.message,
+ });
+
+ // Return error response
+ return new Response(
+ JSON.stringify({
+ error: {
+ message: error.message,
+ type: error.type || 'unknown',
+ code: 500,
+ },
+ }),
+ {
+ status: 500,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ },
+ );
+ }
+ };
+}
+
+/**
+ * Default customFetch implementation (configured via environment variables)
+ */
+export const defaultCustomFetch = createOpenAICustomFetch({
+ apiKey: import.meta.env.VITE_OPENAI_API_KEY,
+ baseURL: 'https://your-chat-backend/api',
+});
+```
+
+Key implementation points:
+
+1. **Multi-turn conversation loop**: Use a `while` loop to handle multiple rounds of tool calls, up to `maxSteps` times
+2. **Message history management**: Maintain a `currentMessages` array containing user messages, assistant messages, and tool call results
+3. **Tool call handling**:
+ - When `finish_reason` is `tool_calls`, execute all tool calls
+ - Add tool call results to `currentMessages` and continue the next round of conversation
+4. **Streaming response conversion**: Convert the OpenAI SDK streaming response to SSE format; otherwise the component cannot process it correctly
+5. **Tool call result delivery**: Send tool execution results via the `tool_calls_result` delta field so the component can update tool call status and display results correctly
+
+#### 3. Use in the Application
+
+Finally, use the custom `customFetch` in a Vue component:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Try Tool Calling
+
+After completing the steps above, you can try tool calling and view tool call arguments and results in the conversation:
+
+
diff --git a/docs/src/en/examples/chat/custom-snippets.md b/docs/src/en/examples/chat/custom-snippets.md
new file mode 100644
index 00000000..3b0025f5
--- /dev/null
+++ b/docs/src/en/examples/chat/custom-snippets.md
@@ -0,0 +1,89 @@
+# Chat Component - Custom Snippets
+
+Custom Snippets provide common component composition patterns to help the LLM quickly generate typical UI structures. Use them together with prompts so the LLM outputs the corresponding schemaJson for these snippets.
+
+## Snippet Definition Format
+
+Each Snippet must include the following fields:
+
+```typescript
+type IGenPromptSnippet = NodeSchema;
+
+
+interface NodeSchema {
+ componentName: string;
+ props?: Record;
+ children?: NodeSchema[];
+ [key: string]: any;
+}
+```
+
+- `componentName`: Component name
+- `props`: Component properties
+- `children`: Child component array used to define the composition structure
+
+## Tabs Composition Example
+
+The following example shows how to use `TinyTabs` and `TinyTabItem` to create a tab layout. `TinyTabs` serves as the container component and `TinyTabItem` as tab items; the two must be used together:
+
+```vue {10-51}
+
+
+
+
+
+
+
+```
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/chat/footer-toolbar.md b/docs/src/en/examples/chat/footer-toolbar.md
new file mode 100644
index 00000000..5a5a2b93
--- /dev/null
+++ b/docs/src/en/examples/chat/footer-toolbar.md
@@ -0,0 +1,73 @@
+# Chat Component - Custom Footer Toolbar
+
+The `GenuiChat` component supports custom footer toolbars for messages from different roles. You can add action buttons below each message (copy, like, dislike, refresh, etc.) to enhance the interaction experience.
+
+## Passing a Custom Footer Toolbar to GenuiChat
+
+Configure message footer toolbars for assistant and user roles via the `roles` prop. Under each role, specify the footer component with `slots.trailer`.
+
+```vue {12-23}
+
+
+
+
+
+
+
+```
+
+## Slot Props
+
+```typescript
+interface IBubbleSlotsProps {
+ index: number;
+ bubbleProps: BubbleProps;
+ isFinished: boolean;
+ messageManager: UseMessageReturn;
+}
+```
+
+- `index`: Index of the current message in the message list (starting from 0)
+- `bubbleProps`: Render props for the current bubble, including `content` and other fields
+- `isFinished`: Whether the current reply has finished; typically used to control toolbar visibility
+- `messageManager`: Message manager containing the current message list, send methods, and more
+
+See TinyRobot documentation for details on `BubbleProps` and `UseMessageReturn`.
+
+See [BubbleProps](https://docs.opentiny.design/tiny-robot/guide/bubble.html#props) for definition and usage.
+
+See [UseMessageReturn](https://docs.opentiny.design/tiny-robot/guide/message.html#%E8%BF%94%E5%9B%9E%E5%80%BC) for definition and usage.
+
+## Creating the User Footer Toolbar Component
+
+See `user-footer.vue` in the full example for detailed code.
+
+## Creating the Assistant Footer Toolbar Component
+
+See `assistant-footer.vue` in the full example for detailed code.
+
+## Full Example
+
+See the runnable demo below:
+
+
diff --git a/docs/src/en/examples/chat/history.md b/docs/src/en/examples/chat/history.md
new file mode 100644
index 00000000..526334dd
--- /dev/null
+++ b/docs/src/en/examples/chat/history.md
@@ -0,0 +1,137 @@
+# Chat Component - Conversation History Management
+
+The `GenuiChat` component includes full conversation management with multi-conversation support, auto-save, and persistent storage. Use the exposed `getConversation()` method to access all conversation management APIs.
+
+## Basic Usage
+
+### Getting the Conversation Object
+
+Access conversation management methods via a component ref:
+
+```vue {12-19}
+
+
+
+
+
+
+
+```
+
+## Conversation Management API
+
+Use the object returned by `getConversation()` to manage conversations:
+
+### Create a New Conversation
+
+```typescript
+const conversation = chatRef.value?.getConversation();
+const newConversationId = conversation?.createConversation('New Conversation Title');
+```
+
+### Switch Conversation
+
+```typescript
+const conversation = chatRef.value?.getConversation();
+conversation?.switchConversation(conversationId);
+```
+
+### Delete Conversation
+
+```typescript
+const conversation = chatRef.value?.getConversation();
+conversation?.deleteConversation(conversationId);
+```
+
+### Manually Save Conversations
+
+```typescript
+const conversation = chatRef.value?.getConversation();
+await conversation?.saveConversations();
+```
+
+## Managing History with a Sidebar
+
+The following example shows how to display and manage conversation history in a sidebar:
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/chat/image-upload.md b/docs/src/en/examples/chat/image-upload.md
new file mode 100644
index 00000000..21e99c1b
--- /dev/null
+++ b/docs/src/en/examples/chat/image-upload.md
@@ -0,0 +1,60 @@
+# Chat Component - Image Upload
+
+The `GenuiChat` component supports image upload, allowing users to upload images in conversations. Configure image upload via `features.supportImage` and pair it with an LLM that supports image processing.
+
+## Configuration Options
+
+```typescript
+interface ImageFeatures {
+ enabled: boolean; // Whether image upload is enabled
+ maxImageSize: number; // Maximum size per image (MB)
+ maxFilesPerRequest: number; // Maximum number of images per request
+ supportedFileTypes: string[]; // Supported image formats
+}
+```
+
+## Basic Usage
+
+Set `supportImage.enabled` to `true` to enable and configure image upload:
+
+```vue {10-16}
+
+
+
+
+
+
+
+```
+
+## Data Format Accepted by the LLM
+
+After upload, the data structure follows the OpenAI-compatible format. The messageItem passed to the LLM looks like this:
+
+```json
+{
+ "role": "user",
+ "content": [
+ { "type": "image_url", "filename": "circle.png", "image_url": { "url": "data:image/png;base64,XXXXXXXXXXX" } },
+ { "type": "text", "text": "Analyze this image" }
+ ]
+}
+```
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/chat/thinking-process.md b/docs/src/en/examples/chat/thinking-process.md
new file mode 100644
index 00000000..07304255
--- /dev/null
+++ b/docs/src/en/examples/chat/thinking-process.md
@@ -0,0 +1,249 @@
+# Chat Component - Custom Thinking Process
+
+The `GenuiChat` component supports a custom thinking-process display component so users can see the AI's real-time response status.
+
+## Basic Usage
+
+Use the `thinkComponent` prop to customize the thinking-process display component.
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Received Props
+
+The custom thinking component receives the following props:
+
+### `message: IChatMessage`
+
+The full message object for this turn of the conversation:
+
+```typescript
+interface IChatMessage {
+ role: 'user' | 'assistant';
+ content: string;
+ messages?: IMessageItem[];
+}
+
+interface IMessageItem {
+ type: string;
+ content: string;
+ [customKey: string]: any;
+}
+```
+
+### `emitter: INotificationEventEmitter`
+
+Used to listen for notification events during streaming responses:
+
+```typescript
+interface INotificationEventEmitter {
+ on(eventName: 'notification', callback: (payload: INotificationPayload) => void, once?: boolean): void;
+ off(eventName: 'notification', callback: (payload: INotificationPayload) => void): void;
+ once(eventName: 'notification', callback: (payload: INotificationPayload) => void): void;
+}
+
+type INotificationPayload =
+ | {
+ type: 'markdown' | 'schema-card' | 'done';
+ delta: IStreamDelta;
+ chatMessage: IChatMessage;
+ }
+ | {
+ type: 'tool';
+ delta: IStreamDelta;
+ chatMessage: IChatMessage;
+ toolCallData: IMessageItem & {
+ type: 'tool';
+ };
+ };
+
+interface IStreamDelta {
+ content?: string;
+ tool_calls?: Array<{
+ id: string;
+ function: {
+ name: string;
+ arguments: string;
+ };
+ }>;
+ tool_calls_result?: Array<{
+ id: string;
+ function: {
+ arguments: any;
+ result: any;
+ };
+ }>;
+}
+```
+
+#### Payload Details
+
+##### 1. `type: 'markdown'`
+
+Triggered when the AI is generating Markdown content:
+
+```typescript
+{
+ type: 'markdown';
+ delta: IStreamDelta; // incremental data, includes the content field
+ chatMessage: IChatMessage; // full message object
+}
+```
+
+**Use case**: When the goal is to generate a card, Markdown can be shown as the thinking process.
+
+##### 2. `type: 'schema-card'`
+
+Triggered when the AI is generating a Schema Card (UI component):
+
+```typescript
+{
+ type: 'schema-card';
+ delta: IStreamDelta;
+ chatMessage: IChatMessage;
+}
+```
+
+**Use case**: Show prompts such as "Generating card...".
+
+##### 3. `type: 'tool'`
+
+Triggered when the AI is invoking a tool:
+
+```typescript
+{
+ type: 'tool';
+ delta: IStreamDelta;
+ chatMessage: IChatMessage;
+ toolCallData: IToolMessageItem; // tool call data
+}
+```
+
+`toolCallData` includes the following fields:
+
+- `name: string` - Tool name
+- `status: 'running' | 'success' | 'failed' | 'cancelled'` - Tool call status
+- `content: string` - Tool call arguments and result (JSON string)
+
+**Use case**: Display tool call status, e.g. "Calling getWeather...", "Called getWeather...".
+
+##### 4. `type: 'done'`
+
+Triggered when the streaming response completes:
+
+```typescript
+{
+ type: 'done';
+ delta: IStreamDelta;
+ chatMessage: IChatMessage;
+}
+```
+
+**Use case**: Hide loading state and clean up temporary data.
+
+## Example Implementation
+
+The following is a thinking component implementation based on production code:
+
+```vue
+
+
+
+ {{ loadingText }}
+
+
+
+```
+
+## Code Explanation
+
+### Event Handling Logic
+
+1. **`done` event**: When streaming completes, clear `loadingText` and hide the component.
+
+2. **`schema-card` event**: When a UI component is being generated, show "Generating card...".
+
+3. **`showThinkingResult` is `true`**: If thinking result display is enabled, always show "Responding..." instead of specific tool call or content generation status.
+
+4. **`tool` event**: Display text based on tool call status (running, success, failed, cancelled), e.g. "Calling getWeather...".
+
+5. **`markdown` event**: Show a preview of the last message content, e.g. "Hello...".
diff --git a/docs/src/en/examples/config-provider/custom-theme.md b/docs/src/en/examples/config-provider/custom-theme.md
new file mode 100644
index 00000000..c76b74ad
--- /dev/null
+++ b/docs/src/en/examples/config-provider/custom-theme.md
@@ -0,0 +1,69 @@
+# GenuiConfigProvider - Custom Theme
+
+`GenuiConfigProvider` supports custom themes via CSS variables. Override CSS variables from TinyRobot and the component library to customize visuals.
+
+## Basic Usage
+
+Use the `id` prop on `GenuiConfigProvider` to create a scoped container, then define custom variables in the matching CSS scope:
+
+```vue {22-43}
+
+
+
+
+
+
+
+```
+
+## TinyRobot Theme Customization
+
+See the [TinyRobot theme configuration guide](https://docs.opentiny.design/tiny-robot/guide/theme-config.html) for more options.
+
+## TinyVue Component Theme Customization
+
+See [component design tokens](https://opentiny.design/tiny-vue/zh-CN/os-theme/components/button#token) for per-component theming.
+
+Or edit [base variables in vars.less](https://github.com/opentiny/tiny-vue/blob/dev/packages/theme/src/base/vars.less) to theme all components globally.
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/config-provider/i18n.md b/docs/src/en/examples/config-provider/i18n.md
new file mode 100644
index 00000000..730705b9
--- /dev/null
+++ b/docs/src/en/examples/config-provider/i18n.md
@@ -0,0 +1,88 @@
+# GenuiConfigProvider - Internationalization
+
+`GenuiConfigProvider` supports i18n via the `locale` prop and custom messages via the `i18n` prop.
+
+## Dynamic Language Switching
+
+Switch language with a reactive variable:
+
+```vue
+
+
+
+ 简体中文
+ English
+
+
+
+
+
+
+
+
+```
+
+## Custom Messages
+
+Use `i18n` to override or extend default strings. Keys are language codes; values are message objects for that locale.
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Full Message Catalog
+
+To customize more strings, inspect the full message catalog:
+
+```typescript
+import { useI18n } from '@opentiny/genui-sdk-vue';
+
+const i18n = useI18n();
+
+console.log(i18n.messages)
+```
+
+## Full Example
+
+
diff --git a/docs/src/en/examples/config-provider/theme.md b/docs/src/en/examples/config-provider/theme.md
new file mode 100644
index 00000000..f460db1c
--- /dev/null
+++ b/docs/src/en/examples/config-provider/theme.md
@@ -0,0 +1,11 @@
+# GenuiConfigProvider - Theme Switching
+
+`GenuiConfigProvider` supports runtime theme switching.
+
+## Theme for GenuiChat
+
+
+
+## Theme for GenuiRenderer
+
+
diff --git a/docs/src/en/examples/renderer/custom-actions.md b/docs/src/en/examples/renderer/custom-actions.md
new file mode 100644
index 00000000..63c70fb3
--- /dev/null
+++ b/docs/src/en/examples/renderer/custom-actions.md
@@ -0,0 +1,151 @@
+# Renderer - Custom Actions
+
+Custom actions let you implement complex interaction logic. Pair them with prompts so the LLM emits schema JSON that invokes those actions.
+
+## Passing customActions to the Renderer
+
+Pass actions via the `customActions` prop. Each action includes:
+
+- `name`: Action name
+- `description`: Action description
+- `execute`: Handler receiving `params` and `context`
+- `parameters`: Optional parameter schema; the model uses it to fill `params` for `execute`
+
+### execute Parameters
+
+- `params`: Arguments passed when the action is invoked
+- `context`: Renderer context (state and methods); use `context.state` for two-way bound global state
+
+### Example 1: Open a Page
+
+```vue {12-35}
+
+
+
+
+
+
+
+```
+
+#### Full Example
+
+
+
+### Example 2: Show Live Form Binding
+
+```vue {12-33}
+
+
+
+
+
+
+
+```
+
+#### Full Example
+
+
+
+## Send Custom Actions to the Server
+
+After registering actions on the renderer, include them in chat requests so the model can generate correct action calls.
+
+```ts {9-30}
+const response = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ messages: [{ role: 'user', content: userInput }],
+ model: 'deepseek-v3.2',
+ stream: true,
+ metadata: {
+ tinygenui: JSON.stringify({
+ customActions: [
+ {
+ name: 'openPage',
+ description: 'Open a page',
+ parameters: {
+ type: 'object',
+ properties: {
+ url: {
+ type: 'string',
+ description: 'URL to open',
+ },
+ target: {
+ type: 'string',
+ description: 'Target window: _self (same tab) or _blank (new tab)',
+ },
+ },
+ required: ['url', 'target'],
+ },
+ }
+ ]
+ }),
+ },
+ }),
+});
+```
diff --git a/docs/src/en/examples/renderer/custom-components.md b/docs/src/en/examples/renderer/custom-components.md
new file mode 100644
index 00000000..80ee0dba
--- /dev/null
+++ b/docs/src/en/examples/renderer/custom-components.md
@@ -0,0 +1,132 @@
+# Renderer - Custom Components
+
+Custom components let you register your own components. With the right prompts, the LLM can output matching `componentName` values in schema JSON for `GenuiRenderer` to render.
+
+## Passing customComponents to the Renderer
+
+Pass a component map via `customComponents` on `GenuiRenderer`.
+
+### Example: Register a Custom Component
+
+```vue {8,13-15}
+
+
+
+
+
+
+
+```
+
+### Create the Custom Component
+
+Use a standard Vue component:
+
+```vue
+
+
+
+
+
+
{{ name?.[0] || 'U' }}
+
+
+
{{ name }}
+
{{ email }}
+
+
+
+
+
+
+
+```
+
+### Use Custom Components in Schema
+
+Generated schema can reference registered components:
+
+```json
+{
+ "componentName": "UserProfile",
+ "props": {
+ "name": "John Doe",
+ "email": "john@example.com",
+ "avatar": "https://example.com/avatar.jpg"
+ }
+}
+```
+
+#### Full Example
+
+
diff --git a/docs/src/en/examples/renderer/required-complete-field-selectors.md b/docs/src/en/examples/renderer/required-complete-field-selectors.md
new file mode 100644
index 00000000..5d990520
--- /dev/null
+++ b/docs/src/en/examples/renderer/required-complete-field-selectors.md
@@ -0,0 +1,122 @@
+# Renderer - Buffered Fields
+
+Use `requiredCompleteFieldSelectors` to declare which field paths must be complete before updates apply. **This mainly prevents render errors when streaming partial JSON.**
+
+## Why Buffered Fields?
+
+During streaming, the LLM emits JSON in fragments. Rendering some fields too early can break the UI, for example:
+
+- **Incomplete JSFunction**: partial `value` under `[type=JSFunction]` causes parse errors
+- **Incomplete componentName**: unknown or partial names fail to render
+- **Incomplete image src**: `[componentName=img] > props > src` may load invalid URLs
+- **Incomplete style**: partial CSS strings may fail to parse
+- **Required component fields**: e.g. `name` on `TinyTabItem`
+
+Buffered selectors tell the framework to hold those values until complete, then apply them in one shot.
+
+## Selector Syntax
+
+Selectors resemble CSS:
+
+### Basics
+
+- **Field name**: `componentName` — any field named `componentName`
+- **Attribute selector**: `[componentName=img]` — nodes where `componentName` is `img`
+- **Child combinator**: `>` — direct child, e.g. `[componentName=img] > props > src`
+- **Descendant**: space — any ancestor relationship
+- **Wildcard**: `*` — any field name
+
+### Attribute Operators
+
+- `=` — exact: `[componentName=img]`
+- `^=` — prefix: `[componentName^=TinyChart]`
+- `$=` — suffix: `[componentName$=Item]`
+- `*=` — contains: `[componentName*=Chart]`
+
+### Pseudo-classes
+
+- `:empty` — empty string, array, or object
+- `:object` — object type
+- `:array` — array type
+- `:string` — string type
+- `:number` — number type
+
+### Examples
+
+```typescript
+// src on img nodes
+'[componentName=img] > props > src';
+
+// All JSFunction nodes
+'[type=JSFunction]';
+
+// All JSExpression nodes
+'[type=JSExpression]';
+
+// All props under components whose name starts with TinyChart
+'[componentName^=TinyChart] > props > *';
+
+// name prop on TinyTabItem
+'[componentName=TinyTabItem] > props > name';
+
+// Empty objects
+':empty:object';
+```
+
+## Defaults
+
+Built-in selectors cover common failure cases:
+
+```typescript
+export const requiredCompleteFieldSelectors = [
+ '[componentName=img] > props > src',
+ 'componentName',
+ 'style',
+ '[type=JSFunction]',
+ '[type=JSExpression]',
+ '[type=JSSlot][value=]',
+ 'type',
+ ':empty:object',
+];
+```
+
+## Custom Configuration
+
+Pass `requiredCompleteFieldSelectors`; custom rules are merged with defaults:
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Notes
+
+1. **Accurate selectors**: Invalid paths are ignored.
+2. **Performance**: Too many selectors can slow updates; prefer critical fragile fields.
diff --git a/docs/src/en/examples/renderer/state.md b/docs/src/en/examples/renderer/state.md
new file mode 100644
index 00000000..932a6e09
--- /dev/null
+++ b/docs/src/en/examples/renderer/state.md
@@ -0,0 +1,64 @@
+# Renderer - Passing and Merging State
+
+Use `state` to pass initial state to the renderer. It is merged into global state on init and accessible from component context.
+
+## Passing State to the Renderer
+
+State is merged when `GenuiRenderer` initializes and **does not update dynamically**.
+
+### Use Case
+
+`state` is mainly for **restoring history**: pass saved state from a past conversation so the renderer can rehydrate.
+
+### Basic Usage
+
+```vue {12-18}
+
+
+
+
+
+
+
+```
+
+### Accessing State in Actions
+
+In custom actions, use `context.state`:
+
+```vue
+
+```
+
+#### Full Example
+
+
+
+## Notes
+
+1. **Init-only merge**: State is merged only on init; later updates are ignored.
+2. **History replay**: Intended for restoring saved conversation state.
+3. **Serializable data**: Avoid functions, DOM nodes, and other non-serializable values.
diff --git a/docs/src/en/guide/angular/install.md b/docs/src/en/guide/angular/install.md
new file mode 100644
index 00000000..14cd2a2f
--- /dev/null
+++ b/docs/src/en/guide/angular/install.md
@@ -0,0 +1,143 @@
+# Installation and Configuration
+
+This guide helps you install GenUI SDK for Angular quickly.
+
+## Install dependencies
+
+Go to your project directory and install GenUI SDK and the official materials package:
+
+::: tabs
+== npm
+```bash
+npm install @opentiny/genui-sdk-angular @opentiny/genui-sdk-materials-angular-opentiny-ng --force # Installs peerDependencies as well
+```
+== pnpm
+```bash
+pnpm add @opentiny/genui-sdk-angular @opentiny/genui-sdk-materials-angular-opentiny-ng @opentiny/ng-themes
+```
+== yarn
+```bash
+yarn add @opentiny/genui-sdk-angular @opentiny/genui-sdk-materials-angular-opentiny-ng @opentiny/ng-themes
+```
+:::
+
+## Import styles
+
+### Update `style.css`
+
+Import the theme files required by the component library:
+
+```css
+@import '@opentiny/ng-themes/styles.css';
+@import '@opentiny/ng-themes/theme-default.css';
+```
+
+## Enable Zone and Animations
+
+The built-in component library requires Zone change detection and the animations module to work correctly.
+
+### Install zone.js
+
+Go to your project directory and install `zone.js`:
+
+::: tabs
+== npm
+```bash
+npm install zone.js
+```
+== pnpm
+```bash
+pnpm add zone.js
+```
+== yarn
+```bash
+yarn add zone.js
+```
+:::
+
+If your project already has Zone.js installed, you can skip this step.
+
+### Update `angular.json`
+
+Add `zone.js` to the polyfills array:
+
+```json
+{
+ // ...
+ "projects": {
+ "your-project-name": {
+ "projectType": "application",
+ // ...
+ "architect": {
+ "build": {
+ "builder": "@angular/build:application",
+ "options": {
+ // ...
+ "polyfills": ["zone.js"] // [!code ++]
+ },
+ // ...
+ },
+ // ....
+ }
+ },
+ // other projects
+ }
+}
+
+```
+
+If your project already configures Zone.js, you can skip this step.
+
+### Update `app.config.ts`
+
+```ts
+// ...
+import { provideAnimations } from '@angular/platform-browser/animations'; // [!code ++]
+import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ // ...
+ provideBrowserGlobalErrorListeners(),
+ provideZoneChangeDetection({ eventCoalescing: true }), // [!code ++]
+ provideAnimations(), // [!code ++]
+ ]
+};
+
+```
+
+## Materials configuration
+
+`GenuiRenderer` no longer ships built-in materials. Inject them via `GenuiConfigProvider`'s `materials` prop so the SDK core stays decoupled from a specific component library.
+
+```ts
+import { Component } from '@angular/core';
+import { GenuiConfigProvider, GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { materials } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/materials';
+
+@Component({
+ imports: [GenuiConfigProvider, GenuiRenderer],
+ template: `
+
+
+
+ `,
+})
+export class GenuiExample {
+ materials = materials;
+ schema = '';
+}
+```
+
+::: tip GenuiLegacyRenderer
+For drop-in compatibility without configuring materials, see [GenuiRenderer Legacy compatibility](../../components/angular/renderer#compatibility-component-genuilegacyrenderer).
+:::
+
+## Next steps
+
+You can now use `GenuiRenderer` to render generative UI. See the [Renderer usage guide](start-with-renderer).
+
+## Related documentation
+
+- See the [Renderer usage guide](start-with-renderer) to learn how to use `GenuiRenderer` with finer control
+- See [feature examples](../../examples/angular/renderer/custom-actions) for usage examples
diff --git a/docs/src/en/guide/angular/start-with-renderer.md b/docs/src/en/guide/angular/start-with-renderer.md
new file mode 100644
index 00000000..77886495
--- /dev/null
+++ b/docs/src/en/guide/angular/start-with-renderer.md
@@ -0,0 +1,184 @@
+# Using the Renderer Component
+
+The core renderer component `GenuiRenderer` lets you compose logic more freely and control flows with finer granularity. This section shows a **minimal working example**: use the browser's native `fetch` to make a **streaming request**, then pass the streamed schema fragments to `GenuiRenderer` for rendering.
+
+## Fetch the service and handle streaming responses
+
+Create a file `fetch-schema-stream.ts`. Parse OpenAI-compatible SSE `delta.content`, then use core `PatternExtractor` to extract `` ```schemaJson `` chunks (default `SchemaJsonPattern`):
+
+````ts
+// fetch-schema-stream.ts
+import { PatternExtractor } from '@opentiny/genui-sdk-core';
+
+export async function fetchSchemaStream(
+ url: string,
+ userInput: string,
+ onSchemaUpdate: (schemaChunk: string) => void,
+): Promise {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ messages: [{ role: 'user', content: userInput }],
+ model: 'deepseek-v3.2',
+ stream: true,
+ metadata: {
+ tinygenui: JSON.stringify({
+ framework: 'Angular',
+ }),
+ },
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder('utf-8');
+ let buffer = '';
+
+ const patternExtractor = new PatternExtractor({
+ onNormalWrite: () => {},
+ onHandledWrite: (value) => onSchemaUpdate(value),
+ });
+
+ try {
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ buffer += decoder.decode(value, { stream: true });
+
+ while (true) {
+ const lineEndIndex = buffer.indexOf('\n');
+ if (lineEndIndex === -1) break;
+
+ const line = buffer.slice(0, lineEndIndex).trim();
+ buffer = buffer.slice(lineEndIndex + 1);
+
+ if (!line.startsWith('data: ')) continue;
+
+ const dataStr = line.slice(6);
+
+ if (dataStr === '[DONE]') {
+ return;
+ }
+
+ try {
+ const chunk = JSON.parse(dataStr);
+ const content = chunk.choices?.[0]?.delta?.content;
+
+ if (!content) continue;
+
+ patternExtractor.handleContent(content);
+ } catch (e) {
+ console.error('Failed to parse backend data:', e, dataStr);
+ }
+ }
+ }
+ } finally {
+ reader.releaseLock();
+ }
+}
+````
+
+## Use the Renderer component to accept streamed schemaJson
+
+Create a simple component with an input, send button, and render area. Configure an LLM service that can generate `schemaJson`:
+
+```ts {8, 15, 61-63}
+import { Component } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { GenuiConfigProvider, GenuiRenderer } from '@opentiny/genui-sdk-angular';
+import { materials } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/materials';
+import { fetchSchemaStream } from '../fetch-schema-stream';
+
+@Component({
+ selector: 'genui-example',
+ imports: [FormsModule, GenuiConfigProvider, GenuiRenderer],
+ template: `
+
+ `,
+ styles: [`
+.demo-container {
+ padding: 16px;
+ box-sizing: border-box;
+}
+
+.input-group {
+ display: flex;
+ gap: 8px;
+ margin-bottom: 16px;
+}
+
+input {
+ flex: 1;
+ padding: 8px 12px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+}
+
+button {
+ padding: 8px 16px;
+ background: #1890ff;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+}
+ `],
+})
+export class GenuiExample {
+ inputText = '';
+ schema = '';
+ rendererKey = '';
+ generating = false;
+ protected readonly activeMaterials = materials;
+ async handleSend() {
+ if (!this.inputText.trim() || this.generating) return;
+
+ this.generating = true;
+ this.schema = '';
+ const userInput = this.inputText;
+ this.inputText = '';
+
+ try {
+ await fetchSchemaStream('https:///chat/completions', userInput, (schemaChunk: string) => {
+ this.schema += schemaChunk;
+ });
+ } catch (error) {
+ console.error('Request failed:', error);
+ } finally {
+ this.generating = false;
+ }
+ }
+ handlePrint(schema: any) {
+ console.log(schema);
+ }
+}
+
+```
+
+::: tip GenuiLegacyRenderer
+For drop-in compatibility without configuring materials, see [GenuiRenderer Legacy compatibility](../../components/angular/renderer#compatibility-component-genuilegacyrenderer).
+:::
+
+## Try it now
+
+Sample output:
+
+
+
+## Related documentation
+
+- See the [Renderer component docs](../../components/angular/renderer) for the full API
+- See [custom actions example](../../examples/angular/renderer/custom-actions) to learn how to create custom actions
diff --git a/docs/src/en/guide/quick-start.md b/docs/src/en/guide/quick-start.md
new file mode 100644
index 00000000..b4802507
--- /dev/null
+++ b/docs/src/en/guide/quick-start.md
@@ -0,0 +1,256 @@
+# Quick Start
+
+This guide helps you get started with GenUI SDK quickly using the `GenuiChat` component.
+
+`GenuiChat` is an integrated chat component with built-in session management, streaming responses, and generation state. It is the simplest way to use generative UI.
+
+## Initialize Project
+
+Create a new Vue project:
+
+```bash
+npm create vue@latest genui-chat
+```
+
+Follow the default prompts to initialize the project.
+
+## Install Dependencies
+
+Install GenUI SDK and the official materials package:
+
+::: tabs
+== npm
+```bash
+cd genui-chat
+npm install @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue
+```
+== pnpm
+```bash
+cd genui-chat
+pnpm add @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue
+```
+== yarn
+```bash
+cd genui-chat
+yarn add @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue
+```
+:::
+
+## Modify Project
+
+### Update `src/main.js` or `src/main.ts`
+
+Remove the default Vue project styles:
+
+```js
+import './assets/main.css'; // [!code --]
+
+import { createApp } from 'vue';
+import App from './App.vue';
+
+createApp(App).mount('#app');
+```
+
+### Update `src/App.vue`
+
+Inject materials via `GenuiConfigProvider` and render `GenuiChat`:
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+## Start Development
+
+Run the dev server:
+
+```bash
+npm run dev
+```
+
+You should now see the GenUI Chat UI in your browser.
+
+## Configure GenuiChat
+
+Configure the LLM via `url`, `model`, and `temperature`:
+
+```vue
+
+
+
+
+
+
+
+
+```
+
+## Materials and Theme with GenuiConfigProvider
+
+Both materials and theme are configured via `GenuiConfigProvider`: `materials` injects UI components, and `theme` controls the appearance.
+
+Built-in theme options:
+
+- `'dark'`: dark theme
+- `'lite'`: fresh theme
+- `'light'`: light theme (default)
+- `'auto'`: follow system preference
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Empty Slot
+
+Use the `empty` slot for welcome text or suggested prompts when there is no conversation:
+
+```vue
+
+
+
+
+ Welcome to Generative UI
+
+
+
+
+```
+
+Add styles:
+
+```css
+.empty-text { /* [!code ++] */
+ height: 100%; /* [!code ++] */
+ display: flex; /* [!code ++] */
+ justify-content: center; /* [!code ++] */
+ align-items: center; /* [!code ++] */
+ font-size: 30px; /* [!code ++] */
+} /* [!code ++] */
+```
+
+### Full Example
+
+```vue
+
+
+
+
+
+
+ Welcome to Generative UI
+
+
+
+
+
+
+```
+
+You are ready to try generative UI.
+
+
+
+## Subpath Imports
+
+Besides the main entry, `@opentiny/genui-sdk-vue` provides subpath exports. Import only Chat or Renderer when needed to avoid bundling unused modules when tree-shaking is limited.
+
+| Subpath | Use case | Main exports |
+| --- | --- | --- |
+| `@opentiny/genui-sdk-vue/chat` | Chat only | `GenuiChat` |
+| `@opentiny/genui-sdk-vue/renderer` | Renderer only (custom chat UI) | `GenuiRenderer` |
+| `@opentiny/genui-sdk-vue/config-provider` | Theme / i18n / materials container | `GenuiConfigProvider` |
+
+```ts
+import { GenuiChat } from '@opentiny/genui-sdk-vue/chat';
+import { GenuiConfigProvider } from '@opentiny/genui-sdk-vue/config-provider';
+import { materials } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/materials';
+
+// Renderer only
+import { GenuiRenderer } from '@opentiny/genui-sdk-vue/renderer';
+```
+
+::: tip
+In v1.3.0, materials were decoupled from the SDK. If you need the built-in TinyVue components without configuring materials separately, use `GenuiLegacyChat`. See [GenuiChat Legacy compatibility](../components/chat#compatibility-component-genuilegacychat).
+:::
+
+## Related Docs
+
+- [GenuiChat API](../components/chat)
+- [Using Renderer](start-with-renderer)
+- [Examples](../examples/chat/custom-actions)
diff --git a/docs/src/en/guide/renderer-with-tiny-robot.md b/docs/src/en/guide/renderer-with-tiny-robot.md
new file mode 100644
index 00000000..eb63f332
--- /dev/null
+++ b/docs/src/en/guide/renderer-with-tiny-robot.md
@@ -0,0 +1,344 @@
+# Using Renderer with TinyRobot
+
+This guide explains how to use the `GenuiRenderer` component with a chat UI such as `TinyRobot`. It demonstrates how to combine a chat component to control message flow, UI rendering, and interaction logic.
+
+## Install dependencies
+
+:::: tabs
+== npm
+```bash
+npm install @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
+```
+== pnpm
+```bash
+pnpm add @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
+```
+== yarn
+```bash
+yarn add @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
+```
+::::
+
+## Basic usage
+
+First, create a custom model provider to handle streaming responses. Below is the full `CustomModelProvider` implementation:
+
+````typescript
+import {
+ BaseModelProvider,
+ type ChatCompletionRequest,
+ type ChatCompletionStreamResponse,
+} from '@opentiny/tiny-robot-kit';
+import { PatternExtractor, type IChatMessage } from '@opentiny/genui-sdk-core';
+import { reactive } from 'vue';
+
+function appendMarkdown(content: string, chatMessage: IChatMessage) {
+ const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
+ if (lastMessage?.type === 'markdown') {
+ lastMessage.content += content;
+ } else {
+ chatMessage.messages.push({ type: 'markdown', content });
+ }
+}
+
+function appendSchemaCard(content: string, chatMessage: IChatMessage) {
+ const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
+ if (lastMessage?.type === 'schema-card') {
+ lastMessage.content += content;
+ } else {
+ chatMessage.messages.push({ type: 'schema-card', content });
+ }
+}
+
+// Split markdown and schemaJson with PatternExtractor (default SchemaJsonPattern)
+function useSchemaStream() {
+ let chatMessageRef: IChatMessage | null = null;
+
+ const patternExtractor = new PatternExtractor({
+ onNormalWrite: (value) => {
+ if (!chatMessageRef) return;
+ chatMessageRef.content += value;
+ appendMarkdown(value, chatMessageRef);
+ },
+ onHandledWrite: (value) => {
+ if (!chatMessageRef) return;
+ chatMessageRef.content += value;
+ appendSchemaCard(value, chatMessageRef);
+ },
+ });
+
+ const handleSchemaStream = (content: string, chatMessage: IChatMessage) => {
+ if (!content || typeof content !== 'string') return;
+ chatMessageRef = chatMessage;
+ patternExtractor.handleContent(content);
+ };
+
+ return { handleSchemaStream };
+}
+
+export class CustomModelProvider extends BaseModelProvider {
+ constructor(private url: string) {
+ super({ provider: 'custom' });
+ }
+
+ async chatStream(
+ request: ChatCompletionRequest,
+ handler: {
+ onData: (data: ChatCompletionStreamResponse) => void;
+ onDone: () => void;
+ onError: (error: any) => void;
+ },
+ ) {
+ const { onDone, onData } = handler;
+ let response: Response;
+
+ try {
+ response = await fetch(this.url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ messages: request.messages,
+ model: 'deepseek-v3.2',
+ stream: true,
+ }),
+ signal: request.options?.signal,
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ } catch (error) {
+ onDone({ type: 'error', error } as any);
+ return;
+ }
+
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder('utf-8');
+ let buffer = '';
+ const { handleSchemaStream } = useSchemaStream();
+
+ const chatMessage = reactive({
+ role: 'assistant',
+ content: '',
+ messages: [],
+ });
+ onData(chatMessage as any);
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ buffer += decoder.decode(value, { stream: true });
+
+ while (true) {
+ const lineEnd = buffer.indexOf('\n');
+ if (lineEnd === -1) break;
+
+ const line = buffer.slice(0, lineEnd).trim();
+ buffer = buffer.slice(lineEnd + 1);
+
+ if (line.startsWith('data: ')) {
+ const data = line.slice(6);
+ if (data === '[DONE]') {
+ onDone();
+ return;
+ }
+
+ try {
+ const chunk = JSON.parse(data);
+ const delta = chunk.choices?.[0]?.delta;
+ const content = delta?.content;
+
+ if (content) {
+ handleSchemaStream(content, chatMessage);
+ const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
+ if (lastMessage && lastMessage.type === 'schema-card' && !lastMessage.id) {
+ // Demo only: use Math.random as key
+ lastMessage.id = Math.random().toString(36).substring(2, 15);
+ }
+ onData(chatMessage as any);
+ }
+ } catch (e) {
+ console.error('Parse error:', e);
+ }
+ }
+ }
+ }
+
+ onDone();
+ }
+}
+````
+
+Then use it in your component:
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+::: tip GenuiRenderer
+For drop-in compatibility without configuring materials, see [GenuiRenderer Legacy compatibility](../components/renderer#compatibility-component-genuilegacyrenderer).
+:::
+
+## Related documentation
+
+- See the [Renderer component docs](../components/renderer) for the full API
+- See [custom components example](../examples/renderer/custom-components) to learn how to create custom components
+- See [custom actions example](../examples/renderer/custom-actions) to learn how to create custom actions
diff --git a/docs/src/en/guide/server-usage.md b/docs/src/en/guide/server-usage.md
new file mode 100644
index 00000000..05ef2035
--- /dev/null
+++ b/docs/src/en/guide/server-usage.md
@@ -0,0 +1,333 @@
+# GenUI SDK Server Usage
+
+The GenUI SDK chat server provides OpenAI-compatible HTTP endpoints with streaming responses and support for multiple AI providers.
+
+## Start the server
+
+### Installation
+
+Global installation:
+
+:::: tabs
+== npm
+```bash
+npm install -g @opentiny/genui-sdk-server
+```
+== pnpm
+```bash
+pnpm add -g @opentiny/genui-sdk-server
+```
+== yarn
+```bash
+yarn global add @opentiny/genui-sdk-server
+```
+::::
+
+Project installation:
+
+:::: tabs
+== npm
+```bash
+npm install @opentiny/genui-sdk-server
+```
+== pnpm
+```bash
+pnpm add @opentiny/genui-sdk-server
+```
+== yarn
+```bash
+yarn add @opentiny/genui-sdk-server
+```
+::::
+
+### Environment configuration
+
+Create a `.env` file:
+
+```env
+BASE_URL=https://api.openai.com/v1
+API_KEY=
+PORT=3100
+```
+
+### Startup options
+
+#### Option 1: CLI command
+
+```bash
+# Use default configuration
+npx genui-sdk-server
+
+# Specify env file (shorthand: -e)
+npx genui-sdk-server --envFile .env.production
+
+# Specify port (shorthand: -p)
+npx genui-sdk-server --port 3000
+
+# Start with environment variables (git bash)
+export API_KEY= BASE_URL=https://your-llm-server.com/api && npx genui-sdk-server
+```
+
+#### Option 2: Programmatic startup
+
+```typescript
+import { startServer } from '@opentiny/genui-sdk-server';
+
+startServer({
+ port: 3100,
+ baseURL: 'https://api.openai.com/v1',
+ apiKey: '',
+ maxAttempts: 10, // Max retries when port is in use
+});
+```
+
+#### Option 3: Integrate into an existing Express app
+
+```typescript
+import express from 'express';
+import { equipChatCompletions } from '@opentiny/genui-sdk-server';
+import cors from 'cors';
+
+const app = express();
+app.use(cors());
+
+equipChatCompletions(app, {
+ route: '/chat/completions',
+ apiKey: '',
+ baseURL: 'https://api.openai.com/v1',
+});
+
+app.listen(3000);
+```
+
+## Client usage
+
+### Chat completions endpoint
+
+**Endpoint**: `POST /chat/completions`
+
+**Request format** (OpenAI-compatible):
+
+```jsonc
+{
+ "model": "gpt-4",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You are a helpful assistant."
+ },
+ {
+ "role": "user",
+ "content": "Hello!"
+ }
+ ],
+ "stream": true,
+ "temperature": 0.7,
+ "metadata": {
+ "tinygenui": "{}" // See tinygenui configuration below
+ }
+}
+```
+
+**Response format** (Server-Sent Events):
+
+```text
+data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
+
+data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}
+
+data: [DONE]
+```
+
+### tinygenui configuration
+
+Pass GenUI configuration via `metadata.tinygenui` to improve LLM generation (JSON string):
+
+```json
+{
+ "framework": "Vue", // or "Angular"
+ "strategy": "append", // "append" | "prepend" | "override"
+ "customComponents": [], // Custom component schema array
+ "customExamples": [], // Custom component usage examples
+ "customSnippets": [], // Custom component snippet schema array
+ "customActions": [] // Custom action definition array
+}
+```
+
+- `framework`: Target frontend framework (Vue or Angular) for renderer configuration
+- `strategy`: Prompt merge strategy
+ - `append`: Append to the existing system message (default)
+ - `prepend`: Prepend to the existing system message
+ - `override`: Replace the existing system message
+- `customComponents`: Custom component schema array to extend the available component list
+- `customExamples`: Custom component usage examples to guide the LLM in generating correct component usage
+- `customSnippets`: Custom component snippet schema array for common component composition patterns
+- `customActions`: Custom action definition array for actions callable from components (e.g. submit form, open a new page)
+
+#### Custom component configuration examples
+
+**customComponents** example:
+
+```js
+const customComponents = [
+ {
+ name: 'User Selector',
+ description: 'Select a user with fuzzy search by name',
+ component: 'TinyUser',
+ schema: {
+ properties: [
+ {
+ property: 'name',
+ description: 'User name to search; supports fuzzy search',
+ type: 'string',
+ required: true,
+ },
+ ],
+ },
+ },
+];
+```
+
+**customExamples** example:
+
+```js
+const customExamples = [
+ {
+ name: 'User selection example',
+ schema: {
+ componentName: 'Page',
+ children: [
+ {
+ componentName: 'h3',
+ props: {},
+ children: 'Enter a username to search and select a user',
+ },
+ {
+ componentName: 'TinyUser',
+ props: {
+ name: 'Zhang San',
+ },
+ },
+ ],
+ },
+ },
+];
+```
+
+**customSnippets** example:
+
+```js
+// Form composition example
+const customSnippets = [
+ {
+ componentName: 'TinyForm',
+ props: {
+ labelPosition: 'top',
+ labelWidth: '120px',
+ },
+ children: [
+ {
+ componentName: 'TinyFormItem',
+ props: {
+ label: 'Name',
+ prop: 'name',
+ required: true,
+ },
+ children: [
+ {
+ componentName: 'TinyInput',
+ props: {
+ placeholder: 'Enter your name',
+ },
+ },
+ ],
+ },
+ {
+ componentName: 'TinyFormItem',
+ props: {
+ label: 'Email',
+ prop: 'email',
+ },
+ children: [
+ {
+ componentName: 'TinyInput',
+ props: {
+ placeholder: 'Enter your email',
+ },
+ },
+ ],
+ },
+ {
+ componentName: 'TinyFormItem',
+ props: {
+ label: '',
+ },
+ children: [
+ {
+ componentName: 'TinyButton',
+ props: {
+ type: 'primary',
+ children: 'Submit',
+ },
+ },
+ ],
+ },
+ ],
+ },
+];
+```
+
+**customActions** example:
+
+```js
+const customActions = [
+ {
+ name: 'openPage',
+ description: 'Open a new page for navigation',
+ parameters: {
+ type: 'object',
+ properties: {
+ url: {
+ type: 'string',
+ description: 'Target page URL or path',
+ },
+ target: {
+ type: 'string',
+ description: 'Open mode: _self (current window) or _blank (new window)',
+ },
+ },
+ required: ['url', 'target'],
+ },
+ },
+];
+```
+
+**Full configuration example**:
+
+```js
+const requestParams = {
+ 'model': 'gpt-4',
+ 'messages': [
+ {
+ 'role': 'system',
+ 'content': 'You are a helpful assistant.',
+ },
+ {
+ 'role': 'user',
+ 'content': 'Hello!',
+ },
+ ],
+ 'stream': true,
+ 'temperature': 0.7,
+ 'metadata': {
+ 'tinygenui': JSON.stringify({
+ framework: 'Vue',
+ strategy: 'append',
+ customComponents,
+ customExamples,
+ customSnippets,
+ customActions,
+ }),
+ },
+};
+```
diff --git a/docs/src/en/guide/start-with-renderer.md b/docs/src/en/guide/start-with-renderer.md
new file mode 100644
index 00000000..04161647
--- /dev/null
+++ b/docs/src/en/guide/start-with-renderer.md
@@ -0,0 +1,174 @@
+# Using the Renderer Component
+
+Besides the integrated Chat component, GenUI SDK provides the core renderer component `GenuiRenderer`, which lets you compose logic more freely and control flows with finer granularity. This section shows a **minimal working example**: use the browser's native `fetch` to make a **streaming request**, then pass the streamed schema fragments to `GenuiRenderer` for rendering.
+
+## Fetch the service and handle streaming responses
+
+Create a file `fetch-schema-stream.ts`. Parse OpenAI-compatible SSE `delta.content`, then use core `PatternExtractor` to extract `` ```schemaJson `` chunks (default `SchemaJsonPattern`):
+
+````typescript
+import { PatternExtractor } from '@opentiny/genui-sdk-core';
+
+export async function fetchSchemaStream(
+ url: string,
+ userInput: string,
+ onSchemaUpdate: (schemaChunk: string) => void,
+): Promise {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ messages: [{ role: 'user', content: userInput }],
+ model: 'deepseek-v3.2',
+ stream: true,
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder('utf-8');
+ let buffer = '';
+
+ const patternExtractor = new PatternExtractor({
+ onNormalWrite: () => {},
+ onHandledWrite: (value) => onSchemaUpdate(value),
+ });
+
+ try {
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ buffer += decoder.decode(value, { stream: true });
+
+ while (true) {
+ const lineEndIndex = buffer.indexOf('\n');
+ if (lineEndIndex === -1) break;
+
+ const line = buffer.slice(0, lineEndIndex).trim();
+ buffer = buffer.slice(lineEndIndex + 1);
+
+ if (!line.startsWith('data:')) continue;
+
+ const dataStr = line.slice(5).trim();
+
+ if (dataStr === '[DONE]') {
+ return;
+ }
+
+ try {
+ const chunk = JSON.parse(dataStr);
+ const content = chunk.choices?.[0]?.delta?.content;
+
+ if (!content) continue;
+
+ patternExtractor.handleContent(content);
+ } catch (e) {
+ console.error('Failed to parse backend data:', e, dataStr);
+ }
+ }
+ }
+ } finally {
+ reader.releaseLock();
+ }
+}
+````
+
+## Use the Renderer component to accept streamed schemaJson
+
+Create a simple Vue component with an input, send button, and render area. Configure an LLM service that can generate `schemaJson`:
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+::: tip GenuiRenderer
+For drop-in compatibility without configuring materials, see [GenuiRenderer Legacy compatibility](../components/renderer#compatibility-component-genuilegacyrenderer).
+:::
+
+## Try it now
+
+This example uses `deepseek-v3.2` for testing. Sample output:
+
+
+
+## Related documentation
+
+- See the [Renderer component docs](../components/renderer) for the full API
+- See [custom components example](../examples/renderer/custom-components) to learn how to create custom components
+- See [custom actions example](../examples/renderer/custom-actions) to learn how to create custom actions
diff --git a/docs/src/en/index.md b/docs/src/en/index.md
new file mode 100644
index 00000000..99cec1d3
--- /dev/null
+++ b/docs/src/en/index.md
@@ -0,0 +1,34 @@
+---
+layout: home
+
+hero:
+ name: 'GenUI-SDK'
+ text: 'Enhance LLM Display & Interaction'
+
+ actions:
+ - theme: brand
+ text: Quick Start
+ link: /en/guide/quick-start
+ - theme: alt
+ text: Components
+ link: /en/components/renderer
+features:
+ - title: AI Ecosystem Compatible
+ details: OpenAI format compatible, supports MCP service integration
+ - title: Customizable Themes
+ details: Theme switching, dark mode, and user-defined themes
+ - title: Custom Components
+ details: Pass custom components and descriptions to enhance generative UI capabilities
+ - title: Custom Interactions
+ details: Custom interaction behaviors such as opening pages and downloading attachments
+ - title: Multi-Stack Support
+ details: Built-in Vue and Angular renderers, with support for custom renderer extensions
+ - title: More Features
+ details: Custom examples and snippets to build better UIs for diverse visual preferences
+---
+
+## What is Generative UI?
+
+Generative UI is an innovative interaction pattern that renders structured LLM output into interactive user interfaces in real time. Unlike plain text chat, generative UI lets AI generate forms, buttons, charts, and other components so users can interact with AI more intuitively and efficiently.
+
+
diff --git a/docs/src/en/schema/protocol.md b/docs/src/en/schema/protocol.md
new file mode 100644
index 00000000..f75ce96c
--- /dev/null
+++ b/docs/src/en/schema/protocol.md
@@ -0,0 +1,808 @@
+
+
+
+
Schema Protocol Specification
+
+
+The Schema protocol is a JSON-based declarative UI description protocol used to define and render user interfaces. It uses a tree structure to describe component hierarchy and supports dynamic data binding and event handling.
+
+## Overview
+
+The Schema protocol describes a complete UI structure through JSON objects, including:
+
+- **Component tree structure**: Describes component hierarchy through nested node objects
+- **Component properties**: Each component can configure properties supporting primitive values, JS expressions, JS functions, and more
+- **State management**: Manages page-level state data through the `state` field
+- **Event handling**: Defines reusable methods through the `methods` field; component properties can bind to these methods
+
+### Design Principles
+
+1. **Declarative**: Uses declarative structures to describe UI rather than imperative operations
+2. **Platform-agnostic**: The protocol itself is not tied to a specific framework; implementations are mapped through a component registry
+3. **Type-safe**: Ensures Schema structure correctness through type definitions
+4. **Extensible**: Supports custom components and property types
+
+## Core Concepts
+
+### Schema Object
+
+A Schema is a JSON object containing a complete page definition. It must include the `componentName` field, typically `"Page"`.
+
+### Node
+
+A node is the basic unit in the component tree; each node represents a UI component. A node includes:
+- `componentName`: Component name (required)
+- `id`: Unique node identifier (optional, but recommended)
+- `props`: Component properties
+- `children`: Child node array
+- Other optional fields: `slot`, `loop`, `condition`, etc.
+
+### RootNode
+
+The root node is the top-level node of a Schema. In addition to all fields of a regular node, it includes page-level configuration:
+- `state`: Global state
+- `methods`: Method collection
+- `css`: Global styles
+
+## Data Structures
+
+### RootNode Type Definition
+
+```typescript
+type RootNode = Omit & {
+ id?: string; // Optional id for root node
+ css?: string; // Global CSS style string
+ fileName?: string; // File name
+ methods?: Methods; // Method collection
+ state?: Record; // Global state
+ schema?: any; // Embedded or external Schema
+};
+```
+
+### Node Type Definition
+
+```typescript
+interface Node {
+ id?: string; // Unique node identifier (optional)
+ componentName: string; // Component name (required)
+ props?: Record & {
+ columns?: { slots?: Record }[]
+ }; // Component property collection
+ children?: Node[]; // Child node array
+ componentType?: 'Block' | 'PageStart' | 'PageSection'; // Node type
+ slot?: string | Record; // Slot content
+ params?: string[]; // Parameter name list
+ loop?: Record; // Loop rendering configuration
+ loopArgs?: string[]; // Loop parameter name list
+ condition?: boolean | Record; // Conditional rendering configuration
+}
+```
+
+### Field Reference
+
+#### Required Fields
+
+- **componentName** (string): Component name; must match a component name in the client component registry
+
+#### Optional Fields
+
+- **id** (string): Unique node identifier; recommended for each node to aid debugging and event handling
+- **props** (object): Component property object; keys are property names, values are property values (supports multiple types)
+- **children** (Node[]): Child node array defining child components
+- **componentType** ('Block' | 'PageStart' | 'PageSection'): Node type; usually omitted
+- **slot** (string | object): Slot content; can be a string or object
+- **params** (string[]): Parameter name list
+- **loop** (object): Loop rendering configuration for list rendering
+- **loopArgs** (string[]): Loop parameter name list, e.g. `["item", "index"]`
+- **condition** (boolean | object): Conditional rendering configuration controlling whether the component renders
+
+#### RootNode-Specific Fields
+
+- **css** (string): Global CSS style string
+- **fileName** (string): File name identifier
+- **methods** (Methods): Method collection defining reusable functions
+- **state** (Record): Global state object
+- **schema** (any): Embedded or external Schema
+
+## Property Value Types
+
+Property values (PropValue) support the following types:
+
+### 1. Primitive Values
+
+- `string`: String
+- `number`: Number
+- `boolean`: Boolean
+- `null`: null value
+
+### 2. JS Expression (JSExpression)
+
+Used for dynamically computing property values; supports accessing state and executing calculations.
+
+```typescript
+interface JSExpression {
+ type: 'JSExpression'; // Fixed as 'JSExpression'
+ value: string; // Expression string
+ model?: boolean; // Whether this is a two-way binding model value
+ params?: string[]; // Parameters passed by scoped slots
+}
+```
+
+**Example:**
+```json
+{
+ "text": {
+ "type": "JSExpression",
+ "value": "this.state.userName + ' - ' + this.state.userHandle"
+ }
+}
+```
+
+**Two-way binding example:**
+```json
+{
+ "value": {
+ "type": "JSExpression",
+ "value": "this.state.inputValue",
+ "model": true
+ }
+}
+```
+
+### 3. JS Function (JSFunction)
+
+Used to define event handler functions.
+
+```typescript
+interface JSFunction {
+ type: 'JSFunction'; // Fixed as 'JSFunction'
+ value: string; // Function body string (serializable)
+}
+```
+
+**Example:**
+```json
+{
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { alert('Button clicked'); }"
+ }
+}
+```
+
+### 4. Slot (JSSlot)
+
+Used to define slot content.
+
+```typescript
+interface JSSlot {
+ type: 'JSSlot'; // Fixed as 'JSSlot'
+ value: string | Record; // Slot content
+}
+```
+
+### 5. Arrays and Objects
+
+Property values can be arrays or objects, supporting nested structures.
+
+```json
+{
+ "items": ["item1", "item2", "item3"],
+ "config": {
+ "key1": "value1",
+ "key2": {
+ "type": "JSExpression",
+ "value": "this.state.dynamicValue"
+ }
+ }
+}
+```
+
+### 6. Special Structure: columns
+
+For table and similar components, `props` supports a special `columns` structure:
+
+```json
+{
+ "props": {
+ "columns": [
+ {
+ "prop": "name",
+ "label": "Name",
+ "slots": {
+ "default": "custom-name-slot"
+ }
+ }
+ ]
+ }
+}
+```
+
+## Component Rendering
+
+### Basic Rendering
+
+Components are specified via the `componentName` field; the client looks up the corresponding implementation in the component registry.
+
+```json
+{
+ "componentName": "Text",
+ "id": "text-1",
+ "props": {
+ "text": "Hello World"
+ }
+}
+```
+
+### Nested Rendering
+
+Child components are defined through the `children` field, forming a component tree.
+
+```json
+{
+ "componentName": "CanvasFlexBox",
+ "id": "container",
+ "props": {
+ "flexDirection": "column"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "id": "title",
+ "props": {
+ "text": "Title"
+ }
+ },
+ {
+ "componentName": "Text",
+ "id": "content",
+ "props": {
+ "text": "Content"
+ }
+ }
+ ]
+}
+```
+
+### Conditional Rendering
+
+The `condition` field controls whether a component renders.
+
+```json
+{
+ "componentName": "Text",
+ "id": "conditional-text",
+ "condition": {
+ "type": "JSExpression",
+ "value": "this.state.isVisible"
+ },
+ "props": {
+ "text": "Conditionally rendered text"
+ }
+}
+```
+
+Or use a boolean value:
+
+```json
+{
+ "componentName": "Text",
+ "id": "conditional-text",
+ "condition": true,
+ "props": {
+ "text": "Conditionally rendered text"
+ }
+}
+```
+
+### Loop Rendering
+
+List rendering is implemented through the `loop` and `loopArgs` fields.
+
+```json
+{
+ "componentName": "div",
+ "id": "list-item",
+ "loop": {
+ "list": {
+ "type": "JSExpression",
+ "value": "this.state.items"
+ }
+ },
+ "loopArgs": ["item", "index"],
+ "props": {
+ "style": "padding: 10px;"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "id": "item-text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "item.name"
+ }
+ }
+ }
+ ]
+}
+```
+
+### Slot Rendering
+
+Slot content is defined through the `slot` field.
+
+```json
+{
+ "componentName": "Card",
+ "id": "card-1",
+ "slot": "Slot content text"
+}
+```
+
+Or define multiple slots using an object:
+
+```json
+{
+ "componentName": "Card",
+ "id": "card-1",
+ "slot": {
+ "header": "Header content",
+ "footer": "Footer content"
+ }
+}
+```
+
+## State Management
+
+### Defining State
+
+Define global state in the `state` field of the root node.
+
+```json
+{
+ "componentName": "Page",
+ "state": {
+ "userName": "John Doe",
+ "userAge": 25,
+ "isLoggedIn": true,
+ "userProfile": {
+ "name": "John Doe",
+ "email": "john@example.com"
+ }
+ }
+}
+```
+
+### Using State
+
+Access state in component properties through JS expressions using `this.state`.
+
+```json
+{
+ "componentName": "Text",
+ "id": "user-name",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "this.state.userName"
+ }
+ }
+}
+```
+
+### Two-Way Binding
+
+For form components, use `model: true` to implement two-way binding.
+
+```json
+{
+ "componentName": "Input",
+ "id": "user-input",
+ "props": {
+ "value": {
+ "type": "JSExpression",
+ "value": "this.state.inputValue",
+ "model": true
+ }
+ }
+}
+```
+
+## Event Handling
+
+### Defining Methods
+
+Define reusable methods in the `methods` field of the root node.
+
+```json
+{
+ "componentName": "Page",
+ "state": {
+ "formData": {
+ "name": "",
+ "email": ""
+ }
+ },
+ "methods": {
+ "handleSubmit": {
+ "type": "JSFunction",
+ "value": "function($event) { console.log('Triggered event object', $event); console.log('Submit data:', this.state.formData); }"
+ }
+ }
+}
+```
+
+### Binding Events
+
+Bind event handler functions in component properties.
+
+**Option 1: Reference a method from methods**
+```json
+{
+ "componentName": "TinyButton",
+ "id": "submit-btn",
+ "props": {
+ "text": "Submit",
+ "onClick": {
+ "type": "JSExpression",
+ "value": "this.handleSubmit"
+ }
+ }
+}
+```
+
+**Option 2: Define JSFunction directly**
+```json
+{
+ "componentName": "TinyButton",
+ "id": "submit-btn",
+ "props": {
+ "text": "Submit",
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { console.log('Submit button clicked'); }"
+ }
+ }
+}
+```
+
+## Complete Examples
+
+### Example 1: Simple Page
+
+```json
+{
+ "componentName": "Page",
+ "fileName": "SimplePage",
+ "css": ".page-base-style {\n padding: 24px;\n background: #FFFFFF;\n}",
+ "props": {
+ "className": "page-base-style"
+ },
+ "children": [
+ {
+ "componentName": "CanvasFlexBox",
+ "id": "container",
+ "props": {
+ "flexDirection": "column",
+ "justifyContent": "center",
+ "alignItems": "center"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "id": "title",
+ "props": {
+ "text": "Welcome to the Schema Protocol",
+ "style": "font-size: 24px; font-weight: bold; margin-bottom: 20px;"
+ }
+ },
+ {
+ "componentName": "Text",
+ "id": "subtitle",
+ "props": {
+ "text": "A declarative Schema-based UI rendering protocol",
+ "style": "font-size: 16px; color: #666;"
+ }
+ }
+ ]
+ }
+ ],
+ "state": {},
+ "methods": {},
+ "id": "body"
+}
+```
+
+### Example 2: Page with State and Events
+
+```json
+{
+ "componentName": "Page",
+ "fileName": "UserProfile",
+ "css": ".page-base-style {\n padding: 24px;\n}",
+ "props": {
+ "className": "page-base-style"
+ },
+ "state": {
+ "userName": "John Doe",
+ "userAvatar": "https://www.example.com/avatar.jpg",
+ "userBio": "Full-stack developer"
+ },
+ "methods": {
+ "handleClick": {
+ "type": "JSFunction",
+ "value": "function() { alert('Button clicked!'); }"
+ }
+ },
+ "children": [
+ {
+ "componentName": "CanvasFlexBox",
+ "id": "profile-container",
+ "props": {
+ "flexDirection": "column",
+ "alignItems": "center",
+ "gap": "20px"
+ },
+ "children": [
+ {
+ "componentName": "img",
+ "id": "avatar",
+ "props": {
+ "src": {
+ "type": "JSExpression",
+ "value": "this.state.userAvatar"
+ },
+ "style": "width: 100px; height: 100px; border-radius: 50%;"
+ }
+ },
+ {
+ "componentName": "Text",
+ "id": "name",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "this.state.userName"
+ },
+ "style": "font-size: 24px; font-weight: bold;"
+ }
+ },
+ {
+ "componentName": "Text",
+ "id": "bio",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "this.state.userBio"
+ },
+ "style": "font-size: 16px; color: #666;"
+ }
+ },
+ {
+ "componentName": "TinyButton",
+ "id": "action-btn",
+ "props": {
+ "text": "Click me",
+ "onClick": {
+ "type": "JSExpression",
+ "value": "this.handleClick"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "id": "body"
+}
+```
+
+### Example 3: List with Loop Rendering
+
+```json
+{
+ "componentName": "Page",
+ "fileName": "ProductList",
+ "state": {
+ "products": [
+ { "id": 1, "name": "Product A", "price": 100 },
+ { "id": 2, "name": "Product B", "price": 200 },
+ { "id": 3, "name": "Product C", "price": 300 }
+ ]
+ },
+ "children": [
+ {
+ "componentName": "CanvasFlexBox",
+ "id": "product-list",
+ "props": {
+ "flexDirection": "column",
+ "gap": "10px"
+ },
+ "children": [
+ {
+ "componentName": "div",
+ "id": "product-item",
+ "loop": {
+ "list": {
+ "type": "JSExpression",
+ "value": "this.state.products"
+ }
+ },
+ "loopArgs": ["item", "index"],
+ "props": {
+ "style": "padding: 10px; border: 1px solid #ddd; border-radius: 4px;"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "id": "product-name",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "item.name"
+ },
+ "style": "font-size: 18px; font-weight: bold;"
+ }
+ },
+ {
+ "componentName": "Text",
+ "id": "product-price",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "'Price: ¥' + item.price"
+ },
+ "style": "font-size: 16px; color: #666;"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "methods": {},
+ "id": "body"
+}
+```
+
+## Type Definitions
+
+### Complete TypeScript Type Definitions
+
+```typescript
+// JS expression
+export type JSExpression = {
+ type: 'JSExpression';
+ value: string;
+ model?: boolean;
+ params?: string[];
+};
+
+// JS function
+export type JSFunction = {
+ type: 'JSFunction';
+ value: string;
+};
+
+// Slot
+export type JSSlot = {
+ type: 'JSSlot';
+ value: string | Record
+};
+
+// Method collection
+export type Methods = Record;
+
+// Property value type (recursive)
+export type PropValue =
+ | string
+ | number
+ | boolean
+ | null
+ | JSExpression
+ | JSFunction
+ | JSSlot
+ | PropValue[]
+ | Record;
+
+// Node interface
+export interface Node {
+ id?: string; // Unique node identifier (optional)
+ componentName: string; // Component name (required)
+ props?: Record & {
+ columns?: { slots?: Record }[]
+ }; // Component property collection
+ children?: Node[]; // Child node array
+ componentType?: 'Block' | 'PageStart' | 'PageSection'; // Node type
+ slot?: string | Record; // Slot content
+ params?: string[]; // Parameter name list
+ loop?: Record; // Loop rendering configuration
+ loopArgs?: string[]; // Loop parameter name list
+ condition?: boolean | Record; // Conditional rendering configuration
+}
+
+// Root node type
+export type RootNode = Omit & {
+ id?: string; // Optional id for root node
+ css?: string; // Global CSS style string
+ fileName?: string; // File name
+ methods?: Methods; // Method collection
+ state?: Record; // Global state
+ schema?: any; // Embedded or external Schema
+};
+```
+
+## Common Components
+
+### Layout Components
+
+- **CanvasFlexBox**: Flexbox layout container
+ - `flexDirection`: Main axis direction ('row' | 'column')
+ - `justifyContent`: Main axis alignment
+ - `alignItems`: Cross axis alignment
+ - `wrap`: Whether to wrap
+ - `gap`: Spacing
+
+- **div**: Generic container
+ - `style`: Inline style string
+ - `className`: CSS class name
+
+### Basic Components
+
+- **Text**: Text component
+ - `text`: Text content
+ - `style`: Style string
+
+- **img**: Image component
+ - `src`: Image URL
+ - `alt`: Alternative text
+ - `style`: Style string
+
+### Business Components
+
+- **TinyTabs**: Tabs component
+ - `modelValue`: Currently active tab
+ - `className`: CSS class name
+
+- **TinyTabItem**: Tab item
+ - `title`: Tab title
+ - `name`: Tab name
+
+- **TinyCarousel**: Carousel component
+ - `height`: Height
+ - `autoplay`: Whether to autoplay
+ - `interval`: Switch interval (milliseconds)
+
+- **TinyCarouselItem**: Carousel item
+ - `title`: Item title
+
+- **TinyButton**: Button component
+ - `text`: Button text
+ - `onClick`: Click event handler
+
+## FAQ
+
+### Q: How do I pass data between components?
+
+A: Define global state through the `state` field; child components access state via JS expressions using `this.state`.
+
+### Q: How do I implement conditional rendering?
+
+A: Use the node's `condition` field, which can be a boolean value or a JS expression.
+
+### Q: How do I implement list rendering?
+
+A: Use the node's `loop` and `loopArgs` fields; `loop` specifies the data source, and `loopArgs` specifies loop variable names.
+
+### Q: How do I implement two-way binding?
+
+A: Set `model: true` in a JSExpression; applicable to form components.
+
+### Q: How do I define component event handlers?
+
+A: There are two approaches:
+1. Define methods in the root node's `methods`, then reference them in component properties using `this.methodName` (e.g. `this.handleClick`)
+2. Define JSFunction directly in component properties
+
+## References
+
+- [TinyEngine Protocol Specification](https://opentiny.design/tiny-engine#/protocol)
diff --git a/docs/src/examples/angular/renderer/custom-actions.md b/docs/src/examples/angular/renderer/custom-actions.md
index 8b3869d5..5175f1f5 100644
--- a/docs/src/examples/angular/renderer/custom-actions.md
+++ b/docs/src/examples/angular/renderer/custom-actions.md
@@ -8,8 +8,10 @@
- `name`: 动作名称
- `description`: 动作描述
+- `parameters`: 参数 JSON Schema 描述
+- `return`: (可选)返回值 JSON Schema 描述,无返回值时可省略
+- `async`: (可选)是否为异步 Action,默认为 `false`;为 `true` 时 `execute` 返回 Promise
- `execute`: 执行函数,接收 `params` 和 `context` 两个参数
-- `params`: 参数定义数组(可选),用于描述动作接收的参数,大模型根据描述生成参数传递给`execute`第一个参数
### execute 函数参数说明
diff --git a/docs/src/examples/chat/custom-actions.md b/docs/src/examples/chat/custom-actions.md
index 9b5c7fcd..75603573 100644
--- a/docs/src/examples/chat/custom-actions.md
+++ b/docs/src/examples/chat/custom-actions.md
@@ -5,15 +5,18 @@
## 基础用法
```vue {14-36}
-
+
+
+
-
+
+
+
```
-完成以上步骤后,即可开始体验生成式 UI 了
+完成以上步骤后,即可开始体验生成式 UI 了。
+

+## 按需引入
+
+`@opentiny/genui-sdk-vue` 除主入口外,还提供按功能拆分的子路径导出。只需 Chat 或只需 Renderer 时,可从对应子路径引入,在构建工具对摇树不友好时,避免打入未使用的模块。
+
+| 子路径 | 适用场景 | 主要导出内容 |
+| --- | --- | --- |
+| `@opentiny/genui-sdk-vue/chat` | 仅需对话组件 | `GenuiChat` |
+| `@opentiny/genui-sdk-vue/renderer` | 仅需渲染器(自建对话 UI) | `GenuiRenderer` |
+| `@opentiny/genui-sdk-vue/config-provider` | 主题/国际化/物料配置容器 | `GenuiConfigProvider` |
+
+```ts
+import { GenuiChat } from '@opentiny/genui-sdk-vue/chat';
+import { GenuiConfigProvider } from '@opentiny/genui-sdk-vue/config-provider';
+import { materials } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/materials';
+
+// 仅使用 Renderer
+import { GenuiRenderer } from '@opentiny/genui-sdk-vue/renderer';
+```
+
+::: tip
+1.3.0 版本进行了物料解耦重构。若需使用内置 TinyVue 组件物料,可使用 `GenuiLegacyChat`,详见 [GenuiChat Legacy 兼容说明](../components/chat#兼容组件-genuilegacychat)。
+:::
+
## 其他相关文档
- 查看 [组件文档](../components/chat) 了解 `GenuiChat` 的详细 API
diff --git a/docs/src/guide/renderer-with-tiny-robot.md b/docs/src/guide/renderer-with-tiny-robot.md
index f1baa591..3693cfc7 100644
--- a/docs/src/guide/renderer-with-tiny-robot.md
+++ b/docs/src/guide/renderer-with-tiny-robot.md
@@ -7,15 +7,15 @@
:::: tabs
== npm
```bash
-npm install @opentiny/genui-sdk-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
+npm install @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
```
== pnpm
```bash
-pnpm add @opentiny/genui-sdk-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
+pnpm add @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
```
== yarn
```bash
-yarn add @opentiny/genui-sdk-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
+yarn add @opentiny/genui-sdk-vue @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/tiny-robot @opentiny/tiny-robot-kit
```
::::
@@ -29,97 +29,48 @@ import {
type ChatCompletionRequest,
type ChatCompletionStreamResponse,
} from '@opentiny/tiny-robot-kit';
+import { PatternExtractor, type IChatMessage } from '@opentiny/genui-sdk-core';
import { reactive } from 'vue';
-import type { IChatMessage } from '@opentiny/genui-sdk-vue';
-// 简化的 Schema 流式处理逻辑(只处理 schema-card 和 markdown)
-function useSchemaStream() {
- let inSchemaStream = false;
- let bufferText = '';
-
- const schemaFlag = '```schemaJson';
- const endFlag = '```';
-
- const isSchemaJsonStart = (str: string): boolean => {
- const index = str.indexOf('`');
- if (index === -1) return false;
- return schemaFlag.startsWith(str.substring(index, index + schemaFlag.length));
- };
-
- const isSchemaJsonEnd = (str: string): boolean => {
- const index = str.lastIndexOf('\n');
- if (index === -1) return false;
- if (str.includes(`\n${endFlag}`)) {
- return true;
- }
- const newStr = str.slice(index).trim().substring(0, endFlag.length);
- return endFlag.startsWith(newStr);
- };
-
- const handleSchemaStream = (content: string, chatMessage: IChatMessage): boolean => {
- if (!content || typeof content !== 'string') return false;
-
- const deltaPart = bufferText + content;
-
- if ((!inSchemaStream && isSchemaJsonStart(deltaPart)) || (inSchemaStream && isSchemaJsonEnd(deltaPart))) {
- const matchFlag = inSchemaStream ? /(\n\s*)```/ : schemaFlag;
- const matchPart = deltaPart.match(matchFlag)?.[0];
- if (!matchPart) {
- bufferText = deltaPart;
- return true;
- }
-
- chatMessage.content += deltaPart;
-
- if (inSchemaStream) {
- const trimmedDelta = deltaPart.trim();
- const [schemaPart, markdownPart] = trimmedDelta.split(matchPart);
- const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
- if (lastMessage?.type === 'schema-card') {
- lastMessage.content += schemaPart;
- }
- if (markdownPart) {
- chatMessage.messages.push({ type: 'markdown', content: markdownPart });
- }
- } else {
- const trimmedDelta = deltaPart.trim();
- const [markdownPart, schemaPart] = trimmedDelta.split(matchPart);
- if (markdownPart) {
- const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
- if (lastMessage && lastMessage.type === 'markdown') {
- lastMessage.content += markdownPart;
- } else {
- chatMessage.messages.push({ type: 'markdown', content: markdownPart });
- }
- }
- chatMessage.messages.push({ type: 'schema-card', content: schemaPart });
- }
-
- inSchemaStream = !inSchemaStream;
- bufferText = '';
- return true;
- }
+function appendMarkdown(content: string, chatMessage: IChatMessage) {
+ const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
+ if (lastMessage?.type === 'markdown') {
+ lastMessage.content += content;
+ } else {
+ chatMessage.messages.push({ type: 'markdown', content });
+ }
+}
- bufferText = '';
+function appendSchemaCard(content: string, chatMessage: IChatMessage) {
+ const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
+ if (lastMessage?.type === 'schema-card') {
+ lastMessage.content += content;
+ } else {
+ chatMessage.messages.push({ type: 'schema-card', content });
+ }
+}
- if (inSchemaStream) {
- chatMessage.content += deltaPart;
- const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
- if (lastMessage && lastMessage.type === 'schema-card') {
- lastMessage.content += deltaPart;
- }
- return true;
- }
+// 用 PatternExtractor 拆分 markdown 与 schemaJson(默认 SchemaJsonPattern)
+function useSchemaStream() {
+ let chatMessageRef: IChatMessage | null = null;
- chatMessage.content += deltaPart;
- const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
- if (lastMessage?.type === 'markdown') {
- lastMessage.content += deltaPart;
- } else {
- chatMessage.messages.push({ type: 'markdown', content: deltaPart });
- }
+ const patternExtractor = new PatternExtractor({
+ onNormalWrite: (value) => {
+ if (!chatMessageRef) return;
+ chatMessageRef.content += value;
+ appendMarkdown(value, chatMessageRef);
+ },
+ onHandledWrite: (value) => {
+ if (!chatMessageRef) return;
+ chatMessageRef.content += value;
+ appendSchemaCard(value, chatMessageRef);
+ },
+ });
- return false;
+ const handleSchemaStream = (content: string, chatMessage: IChatMessage) => {
+ if (!content || typeof content !== 'string') return;
+ chatMessageRef = chatMessage;
+ patternExtractor.handleContent(content);
};
return { handleSchemaStream };
@@ -224,7 +175,9 @@ export class CustomModelProvider extends BaseModelProvider {
```vue
-
-
+
```
+::: tip GenuiRenderer
+若无需单独配置物料、需兼容 1.3.0 之前用法,见 [GenuiRenderer Legacy 兼容说明](../components/renderer#兼容组件-genuilegacyrenderer)。
+:::
+
## 其他相关文档
- 查看 [Renderer 组件文档](../components/renderer) 了解详细的 API
diff --git a/docs/src/guide/server-usage.md b/docs/src/guide/server-usage.md
index 5ee51e70..67138260 100644
--- a/docs/src/guide/server-usage.md
+++ b/docs/src/guide/server-usage.md
@@ -108,7 +108,7 @@ app.listen(3000);
**请求格式**(OpenAI 兼容):
-```json
+```jsonc
{
"model": "gpt-4",
"messages": [
@@ -131,7 +131,7 @@ app.listen(3000);
**响应格式**(Server-Sent Events):
-```
+```text
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-4","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}
diff --git a/docs/src/guide/start-with-renderer.md b/docs/src/guide/start-with-renderer.md
index 5f71cd2c..577bc3fe 100644
--- a/docs/src/guide/start-with-renderer.md
+++ b/docs/src/guide/start-with-renderer.md
@@ -4,9 +4,11 @@
## 使用 fetch 请求服务,处理流式返回
-创建一个文件 `fetch-schema-stream.ts`, 文件中的处理逻辑都是基于 OpenAI 兼容格式处理:
+创建一个文件 `fetch-schema-stream.ts`。基于 OpenAI 兼容 SSE 解析 `delta.content`,再用 core 的 `PatternExtractor` 提取 `` ```schemaJson `` 片段(默认 `SchemaJsonPattern`):
````typescript
+import { PatternExtractor } from '@opentiny/genui-sdk-core';
+
export async function fetchSchemaStream(
url: string,
userInput: string,
@@ -26,33 +28,14 @@ export async function fetchSchemaStream(
throw new Error(`HTTP error! status: ${response.status}`);
}
- const reader = response.body.getReader();
+ const reader = response.body!.getReader();
const decoder = new TextDecoder('utf-8');
let buffer = '';
- let inSchemaStream = false;
- let bufferText = '';
- let schemaFinished = false;
- const startFlag = '```schemaJson';
- const endFlag = '```';
-
- // 检测 schema 开始标记
- const isSchemaJsonStart = (str: string): boolean => {
- const index = str.indexOf('`');
- if (index === -1) return false;
- return startFlag.startsWith(str.substring(index, index + startFlag.length));
- };
-
- // 检测 schema 结束标记
- const isSchemaJsonEnd = (str: string): boolean => {
- const index = str.lastIndexOf('\n');
- if (index === -1) return false;
- if (str.includes(`\n${endFlag}`)) {
- return true;
- }
- const newStr = str.slice(index).trim().substring(0, endFlag.length);
- return endFlag.startsWith(newStr);
- };
+ const patternExtractor = new PatternExtractor({
+ onNormalWrite: () => {},
+ onHandledWrite: (value) => onSchemaUpdate(value),
+ });
try {
while (true) {
@@ -72,7 +55,7 @@ export async function fetchSchemaStream(
const dataStr = line.slice(5).trim();
- if (dataStr === '[DONE]' || schemaFinished) {
+ if (dataStr === '[DONE]') {
return;
}
@@ -82,43 +65,7 @@ export async function fetchSchemaStream(
if (!content) continue;
- const deltaPart = bufferText + content;
-
- // 检测是否进入或退出 schema 流
- if ((!inSchemaStream && isSchemaJsonStart(deltaPart)) || (inSchemaStream && isSchemaJsonEnd(deltaPart))) {
- const matchFlag = inSchemaStream ? /(\n\s*)```/ : startFlag;
- const matchPart = deltaPart.match(matchFlag)?.[0];
-
- if (!matchPart) {
- // 标记不完整,保留到下次
- bufferText = deltaPart;
- continue;
- }
-
- if (inSchemaStream) {
- const trimmedDelta = deltaPart.trim();
- const [schemaPart] = trimmedDelta.split(matchPart);
- if (schemaPart) {
- onSchemaUpdate(schemaPart);
- }
- schemaFinished = true;
- return;
- } else {
- const trimmedDelta = deltaPart.trim();
- const [, schemaPart] = trimmedDelta.split(matchPart);
- inSchemaStream = true;
- bufferText = '';
- if (schemaPart) {
- onSchemaUpdate(schemaPart);
- }
- continue;
- }
- }
-
- bufferText = '';
- if (inSchemaStream) {
- onSchemaUpdate(deltaPart);
- }
+ patternExtractor.handleContent(content);
} catch (e) {
console.error('解析后端数据失败:', e, dataStr);
}
@@ -136,18 +83,22 @@ export async function fetchSchemaStream(
```vue
-
-
+
-
+
```
+
## Documentation
* [quick-start](https://docs.opentiny.design/genui-sdk/guide/quick-start)
@@ -34,4 +42,4 @@ import { GenuiChat, GenuiConfigProvider } from '@opentiny/genui-sdk-vue';
* [GenuiRender](https://docs.opentiny.design/genui-sdk/components/renderer)
* [GenuiChat](https://docs.opentiny.design/genui-sdk/components/chat)
-* [GenuiConfigProvider](https://docs.opentiny.design/genui-sdk/components/config-provider)
\ No newline at end of file
+* [GenuiConfigProvider](https://docs.opentiny.design/genui-sdk/components/config-provider)
diff --git a/packages/frameworks/vue/package.json b/packages/frameworks/vue/package.json
index a37414b6..1b0870c8 100644
--- a/packages/frameworks/vue/package.json
+++ b/packages/frameworks/vue/package.json
@@ -20,28 +20,36 @@
"generative-ui",
"stream-ui"
],
- "main": "output/dist/index.js",
- "types": "output/dist/index.d.ts",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
"exports": {
".": {
- "types": "./output/dist/index.d.ts",
- "import": "./output/dist/index.js"
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
},
"./chat": {
- "types": "./output/dist/chat.d.ts",
- "import": "./output/dist/chat.js"
+ "types": "./dist/chat.d.ts",
+ "import": "./dist/chat.js"
+ },
+ "./legacy-chat": {
+ "types": "./dist/legacy-chat.d.ts",
+ "import": "./dist/legacy-chat.js"
},
"./renderer": {
- "types": "./output/dist/renderer.d.ts",
- "import": "./output/dist/renderer.js"
+ "types": "./dist/renderer.d.ts",
+ "import": "./dist/renderer.js"
+ },
+ "./legacy-renderer": {
+ "types": "./dist/legacy-renderer.d.ts",
+ "import": "./dist/legacy-renderer.js"
},
"./config-provider": {
- "types": "./output/dist/config-provider.d.ts",
- "import": "./output/dist/config-provider.js"
+ "types": "./dist/config-provider.d.ts",
+ "import": "./dist/config-provider.js"
},
"./transform-jsx": {
- "types": "./output/dist/transform-jsx.d.ts",
- "import": "./output/dist/transform-jsx.js"
+ "types": "./dist/transform-jsx.d.ts",
+ "import": "./dist/transform-jsx.js"
}
},
"type": "module",
@@ -51,60 +59,27 @@
],
"scripts": {
"build": "vite build",
- "postbuild": "tsx scripts/postbuild.ts",
"analyze": "vite build --mode analyze",
"prebuild:lib:npm": "pnpm -F @opentiny/genui-sdk-core build && pnpm -F @opentiny/genui-sdk-materials-vue-opentiny-vue build && pnpm -F @opentiny/tiny-schema-renderer build",
"build:lib:npm": "pnpm build",
"test": "vitest"
},
"dependencies": {
+ "@opentiny/genui-sdk-core": "workspace:*",
+ "@opentiny/genui-sdk-materials-vue-opentiny-vue": "workspace:*",
"@opentiny/tiny-robot": "0.3.3",
"@opentiny/tiny-robot-kit": "0.3.3",
"@opentiny/tiny-robot-svgs": "0.3.3",
- "@opentiny/vue": "^3.28.0",
- "@opentiny/vue-renderless": "^3.28.2",
- "@opentiny/vue-icon": "^3.28.0",
- "@opentiny/vue-theme": "^3.28.0",
+ "@opentiny/vue": "~3.28.0",
+ "@opentiny/vue-renderless": "~3.28.2",
+ "@opentiny/vue-icon": "~3.28.0",
+ "@opentiny/vue-theme": "~3.28.0",
"uuid": "^11.1.0",
"vue": "^3.5.13",
- "@opentiny/vue-chart-bar": "~3.14.0",
- "@opentiny/vue-chart-histogram": "~3.14.0",
- "@opentiny/vue-chart-line": "~3.14.0",
- "@opentiny/vue-chart-pie": "~3.14.0",
- "@opentiny/vue-chart-radar": "~3.14.0",
- "@opentiny/vue-chart-ring": "3.14.0",
- "@opentiny/vue-carousel": "^3.28.0",
- "@opentiny/vue-carousel-item": "^3.28.0",
- "@opentiny/vue-checkbox-button": "^3.28.0",
- "@opentiny/vue-checkbox-group": "^3.28.0",
- "@opentiny/vue-col": "^3.28.0",
- "@opentiny/vue-date-picker": "^3.28.0",
- "@opentiny/vue-layout": "^3.28.0",
- "@opentiny/vue-row": "^3.28.0",
- "@opentiny/vue-search": "^3.28.0",
- "@opentiny/vue-select": "^3.28.0",
- "@opentiny/vue-transfer": "^3.28.0",
- "@opentiny/vue-button": "^3.28.0",
- "@opentiny/vue-grid": "^3.28.0",
- "@opentiny/vue-form": "^3.28.0",
- "@opentiny/vue-form-item": "^3.28.0",
- "@opentiny/vue-input": "^3.28.0",
- "@opentiny/vue-notify": "^3.28.0",
- "@opentiny/vue-card": "^3.28.0",
- "@opentiny/vue-checkbox": "^3.28.0",
- "@opentiny/vue-numeric": "^3.28.0",
- "@opentiny/vue-radio": "^3.28.0",
- "@opentiny/vue-switch": "^3.28.0",
- "@opentiny/vue-tabs": "^3.28.0",
- "@opentiny/vue-tab-item": "^3.28.0",
- "@opentiny/vue-tree": "^3.28.0",
- "@opentiny/vue-radio-group": "^3.28.0",
"@opentiny/tiny-engine-builtin-component": "^2.6.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.0",
- "@opentiny/genui-sdk-core": "workspace:*",
- "@opentiny/genui-sdk-materials-vue-opentiny-vue": "workspace:*",
"@opentiny/tiny-schema-renderer": "workspace:*",
"rollup-plugin-visualizer": "^6.0.5",
"vite-plugin-css-injected-by-js": "^3.5.2",
diff --git a/packages/frameworks/vue/scripts/postbuild.ts b/packages/frameworks/vue/scripts/postbuild.ts
deleted file mode 100644
index 43af7bb8..00000000
--- a/packages/frameworks/vue/scripts/postbuild.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { readFileSync, writeFileSync, copyFileSync } from 'node:fs';
-import { fileURLToPath } from 'node:url';
-import { basename, dirname, join } from 'node:path';
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-const packageJsonPath = join(__dirname, '../package.json');
-const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
-
-const outputDir = join(__dirname, '../output');
-const packageJsonOutputPrefix = `${basename(outputDir)}/`;
-
-// 创建新的 package.json 对象,只包含需要的字段
-const outputPackageJson: any = {
- name: packageJson.name,
- version: packageJson.version,
- description: packageJson.description,
- author: packageJson.author,
- license: packageJson.license,
- homepage: packageJson.homepage,
- repository: packageJson.repository,
- bugs: packageJson.bugs,
- keywords: packageJson.keywords,
- main: packageJson.main.replace(packageJsonOutputPrefix, ''),
- types: packageJson.types.replace(packageJsonOutputPrefix, ''),
- exports: normalizeExports(packageJson.exports, packageJsonOutputPrefix),
- type: packageJson.type,
- files: packageJson.files,
- dependencies: { ...packageJson.dependencies },
-};
-
-// 修改 @opentiny/genui-sdk-core 的版本(从 "workspace:*" 改为实际版本号)
-if (outputPackageJson.dependencies && outputPackageJson.dependencies['@opentiny/genui-sdk-core'] === 'workspace:*') {
- const corePackageJsonPath = join(__dirname, '../../../core/package.json');
- const corePackageJson = JSON.parse(readFileSync(corePackageJsonPath, 'utf-8'));
- outputPackageJson.dependencies['@opentiny/genui-sdk-core'] = corePackageJson.version;
-}
-
-const outputPackageJsonPath = join(outputDir, 'package.json');
-writeFileSync(outputPackageJsonPath, JSON.stringify(outputPackageJson, null, 2) + '\n', 'utf-8');
-
-// 复制 packages/server/README.md 到 output 文件夹
-const serverReadmePath = join(__dirname, '../README.md');
-const outputReadmePath = join(outputDir, 'README.md');
-copyFileSync(serverReadmePath, outputReadmePath);
-
-function normalizeExports(exportsField: Record
= {}, outputPathPrefix: string) {
- return Object.fromEntries(
- Object.entries(exportsField).map(([subpath, condition]) => {
- if (typeof condition === 'string') {
- return [subpath, condition.replace(outputPathPrefix, '')];
- }
-
- const normalizedCondition = Object.fromEntries(
- Object.entries(condition || {}).map(([conditionName, target]) => [
- conditionName,
- String(target).replace(outputPathPrefix, ''),
- ]),
- );
-
- return [subpath, normalizedCondition];
- }),
- );
-}
diff --git a/packages/frameworks/vue/src/chat/CustomModelProvider.ts b/packages/frameworks/vue/src/chat/CustomModelProvider.ts
index 1ea2220b..92139f7e 100644
--- a/packages/frameworks/vue/src/chat/CustomModelProvider.ts
+++ b/packages/frameworks/vue/src/chat/CustomModelProvider.ts
@@ -99,8 +99,7 @@ export class CustomModelProvider extends BaseModelProvider {
const reader = bodyStream.getReader();
const context: any = {};
- const { chatConfig } = this.getChatOptions();
- context.chatConfig = chatConfig;
+ this.setupStreamContext(context, request);
const signal = request.options?.signal;
signal?.addEventListener('abort',
@@ -120,6 +119,11 @@ export class CustomModelProvider extends BaseModelProvider {
}
+ protected setupStreamContext(context: Record, _request: ChatCompletionRequest) {
+ const { chatConfig } = this.getChatOptions();
+ context.chatConfig = chatConfig;
+ }
+
handlerChunk(rawData: string, context: any) {
try {
const streamData = JSON.parse(rawData) as IStreamData;
diff --git a/packages/frameworks/vue/src/chat/GeneratingComponent.vue b/packages/frameworks/vue/src/chat/GeneratingComponent.vue
index f0645273..37f2da8d 100644
--- a/packages/frameworks/vue/src/chat/GeneratingComponent.vue
+++ b/packages/frameworks/vue/src/chat/GeneratingComponent.vue
@@ -10,6 +10,8 @@ const { t } = useI18n();
const loadingText = ref(t('loading.response'));
+const hasSchemaCard = ref(false);
+
const toolStatusTextMap = new Map([
['running', { textKey: 'toolStatus.running' }],
['success', { textKey: 'toolStatus.success' }],
@@ -43,7 +45,10 @@ const handleNotification = (payload: INotificationPayload) => {
// type === 'markdown'
const lastMessage = payload.chatMessage.messages[payload.chatMessage.messages.length - 1];
if (lastMessage) {
- loadingText.value = `${lastMessage.content}...`;
+ if (!hasSchemaCard.value) {
+ hasSchemaCard.value = payload.chatMessage.messages?.some((item: any) => item.type.startsWith('schema-card'));
+ }
+ loadingText.value = hasSchemaCard.value ? `${lastMessage.content}...` : t('loading.response');
}
};
@@ -58,7 +63,7 @@ onBeforeUnmount(() => {
-
{{ loadingText }}
+
{{ loadingText }}
-
-
-
\ No newline at end of file
+}
+
+
+
diff --git a/packages/frameworks/vue/src/chat/response-handler.ts b/packages/frameworks/vue/src/chat/response-handler.ts
index eff57010..3f16f1e4 100644
--- a/packages/frameworks/vue/src/chat/response-handler.ts
+++ b/packages/frameworks/vue/src/chat/response-handler.ts
@@ -1,6 +1,6 @@
-import { IChatMessage, IMessageItem, IStreamDelta, IStreamData, PatternExtractor } from "@opentiny/genui-sdk-core";
+import { IChatMessage, IMessageItem, IStreamDelta, IStreamData, PatternExtractor } from '@opentiny/genui-sdk-core';
import { ThinkTagWrapPattern } from './think-tag-wrap-pattern';
-import { reactive, toRaw, watch } from "vue";
+import { reactive, readonly, watch } from 'vue';
import { v4 as uuidv4 } from 'uuid';
import { emitter } from './event-emitter';
import { useI18n } from './i18n';
@@ -10,7 +10,10 @@ export interface IResponseHandler {
match: (data: T, context: any) => boolean;
handler: (data: T, context: any) => boolean;
notMatchHandler?: (data: T, context: any) => boolean;
- start?: (context: any, handlers: { onData: (data: IChatMessage) => void, onDone: () => void, onError: (error: Error) => void }) => void;
+ start?: (
+ context: any,
+ handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },
+ ) => void;
end?: (context: any) => void;
}
@@ -18,7 +21,13 @@ const getStreamDelta = (data: IStreamData): IStreamDelta => {
return data.choices?.[0]?.delta ?? {};
};
-function onToolResult(toolCallsResult: any[], delta: IStreamDelta, toolCallIdMap: Record, chatMessage: IChatMessage, addToolCallContext: boolean) {
+function onToolResult(
+ toolCallsResult: any[],
+ delta: IStreamDelta,
+ toolCallIdMap: Record,
+ chatMessage: IChatMessage,
+ addToolCallContext: boolean,
+) {
const {
id,
function: { arguments: args, result },
@@ -31,8 +40,8 @@ function onToolResult(toolCallsResult: any[], delta: IStreamDelta, toolCallIdMap
emitter.emit('notification', {
type: 'tool',
delta,
- toolCallData: structuredClone(toRaw(toolCallItem)),
- chatMessage: structuredClone(toRaw(chatMessage)),
+ toolCallData: readonly(toolCallItem),
+ chatMessage: readonly(chatMessage),
});
if (addToolCallContext) {
@@ -45,9 +54,15 @@ function onToolResult(toolCallsResult: any[], delta: IStreamDelta, toolCallIdMap
}) + '\n\n';
}
}
-};
+}
-function onToolCall(toolCalls: any[], delta: IStreamDelta, toolCallIdMap: Record, chatMessage: IChatMessage, toolCallStatus: { inProcessToolCallId: string | null }) {
+function onToolCall(
+ toolCalls: any[],
+ delta: IStreamDelta,
+ toolCallIdMap: Record,
+ chatMessage: IChatMessage,
+ toolCallStatus: { inProcessToolCallId: string | null },
+) {
toolCalls.forEach((toolCall) => {
const {
id,
@@ -79,17 +94,15 @@ function onToolCall(toolCalls: any[], delta: IStreamDelta, toolCallIdMap: Record
emitter.emit('notification', {
type: 'tool',
delta,
- toolCallData: toolCallItem,
- chatMessage: structuredClone(toRaw(chatMessage)),
+ toolCallData: readonly(toolCallItem),
+ chatMessage: readonly(chatMessage),
});
-
});
-
-};
+}
function onReasoningContent(reasoningContent: string, delta: IStreamDelta, chatMessage: IChatMessage) {
const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
- let reasoningMessage = lastMessage
+ let reasoningMessage = lastMessage;
if (reasoningMessage?.type === 'reasoning') {
reasoningMessage.content += reasoningContent;
} else {
@@ -102,11 +115,11 @@ function onReasoningContent(reasoningContent: string, delta: IStreamDelta, chatM
}
emitNotification(delta, chatMessage);
return reasoningMessage;
-};
+}
function onReasoningEnd(reasoningMessage: IMessageItem) {
if (reasoningMessage?.type === 'reasoning') reasoningMessage.thinking = false;
-};
+}
function emitNotification(delta: IStreamDelta, chatMessage: IChatMessage) {
const lastMessage = chatMessage.messages[chatMessage.messages.length - 1];
@@ -114,10 +127,10 @@ function emitNotification(delta: IStreamDelta, chatMessage: IChatMessage) {
emitter.emit('notification', {
type: lastMessage.type as 'markdown' | 'schema-card',
delta,
- chatMessage: structuredClone(toRaw(chatMessage)),
+ chatMessage: readonly(chatMessage),
});
}
-};
+}
function onMarkdown(content: string, delta: IStreamDelta, chatMessage: IChatMessage) {
if (chatMessage.messages.length > 0 && chatMessage.messages[chatMessage.messages.length - 1].type === 'markdown') {
@@ -125,11 +138,11 @@ function onMarkdown(content: string, delta: IStreamDelta, chatMessage: IChatMess
} else {
chatMessage.messages.push({
type: 'markdown',
- content: content
+ content: content,
});
}
emitNotification(delta, chatMessage);
-};
+}
function onSchemaJSON(content: string, delta: IStreamDelta, chatMessage: IChatMessage) {
if (chatMessage.messages.length > 0 && chatMessage.messages[chatMessage.messages.length - 1].type === 'schema-card') {
@@ -144,14 +157,18 @@ function onSchemaJSON(content: string, delta: IStreamDelta, chatMessage: IChatMe
emitNotification(delta, chatMessage);
}
-function watchReasoningEnd (context: any) {
- context.unWatchReasoning = watch(() => [...context.chatMessage.messages], (newVal) => {
- if (context.handleReasoning && newVal[newVal.length - 1]?.type !== 'reasoning') {
- context.handleReasoning = false;
- onReasoningEnd(context.reasoningMessage);
- context.unWatchReasoning?.();
- }
- }, { flush: 'sync' });
+function watchReasoningEnd(context: any) {
+ context.unWatchReasoning = watch(
+ () => [...context.chatMessage.messages],
+ (newVal) => {
+ if (context.handleReasoning && newVal[newVal.length - 1]?.type !== 'reasoning') {
+ context.handleReasoning = false;
+ onReasoningEnd(context.reasoningMessage);
+ context.unWatchReasoning?.();
+ }
+ },
+ { flush: 'sync' },
+ );
}
export const defaultResponseHandlers: IResponseHandler[] = [
@@ -159,7 +176,10 @@ export const defaultResponseHandlers: IResponseHandler[] = [
name: 'init',
match: (data: IStreamData, context: any) => false,
handler: (data: IStreamData, context: any) => false,
- start: (context: any, handlers: { onData: (data: IChatMessage) => void, onDone: () => void, onError: (error: Error) => void }) => {
+ start: (
+ context: any,
+ handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },
+ ) => {
const chatMessage = reactive({
role: 'assistant',
content: '',
@@ -175,7 +195,7 @@ export const defaultResponseHandlers: IResponseHandler[] = [
emitter.emit('notification', {
type: 'done',
delta: {},
- chatMessage: structuredClone(toRaw(context.chatMessage)),
+ chatMessage: readonly(context.chatMessage),
});
},
},
@@ -205,7 +225,10 @@ export const defaultResponseHandlers: IResponseHandler[] = [
}
return true;
},
- start: (context: any, handlers: { onData: (data: IChatMessage) => void, onDone: () => void, onError: (error: Error) => void }) => {
+ start: (
+ context: any,
+ handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },
+ ) => {
context.handleReasoning = false;
},
end: (context: any) => {
@@ -214,7 +237,7 @@ export const defaultResponseHandlers: IResponseHandler[] = [
context.handleReasoning = false;
onReasoningEnd(context.reasoningMessage);
}
- }
+ },
},
{
name: 'toolCall',
@@ -227,7 +250,10 @@ export const defaultResponseHandlers: IResponseHandler[] = [
onToolCall(delta.tool_calls, delta, context.toolCallIdMap, context.chatMessage, context.toolCallStatus);
return true;
},
- start: (context: any, handlers: { onData: (data: IChatMessage) => void, onDone: () => void, onError: (error: Error) => void }) => {
+ start: (
+ context: any,
+ handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },
+ ) => {
context.toolCallIdMap = {};
context.toolCallStatus = { inProcessToolCallId: null };
},
@@ -240,7 +266,13 @@ export const defaultResponseHandlers: IResponseHandler[] = [
},
handler: (data: IStreamData, context: any) => {
const delta = getStreamDelta(data);
- onToolResult(delta.tool_calls_result, delta, context.toolCallIdMap, context.chatMessage, context.chatConfig.addToolCallContext);
+ onToolResult(
+ delta.tool_calls_result,
+ delta,
+ context.toolCallIdMap,
+ context.chatMessage,
+ context.chatConfig.addToolCallContext,
+ );
return true;
},
},
@@ -253,15 +285,18 @@ export const defaultResponseHandlers: IResponseHandler[] = [
handler: (data: IStreamData, context: any) => {
const delta = getStreamDelta(data);
context.delta = delta;
- context.patternExtractor.handleContent(delta.content)
+ context.patternExtractor.handleContent(delta.content);
context.chatMessage.content += delta.content;
return true;
},
- start: (context: any, handlers: { onData: (data: IChatMessage) => void, onDone: () => void, onError: (error: Error) => void }) => {
+ start: (
+ context: any,
+ handlers: { onData: (data: IChatMessage) => void; onDone: () => void; onError: (error: Error) => void },
+ ) => {
const thinkPatternExtractor = new PatternExtractor({
onNormalWrite: (value) => onMarkdown(value, context.delta, context.chatMessage),
- onHandledWrite: (value) => {
- context.reasoningMessage = onReasoningContent(value, context.delta, context.chatMessage)
+ onHandledWrite: (value) => {
+ context.reasoningMessage = onReasoningContent(value, context.delta, context.chatMessage);
if (!context.handleReasoning) {
watchReasoningEnd(context);
context.handleReasoning = true;
@@ -274,5 +309,5 @@ export const defaultResponseHandlers: IResponseHandler[] = [
onHandledWrite: (value) => onSchemaJSON(value, context.delta, context.chatMessage),
});
},
- }
+ },
];
diff --git a/packages/frameworks/vue/src/chat/think-tag-wrap-pattern.ts b/packages/frameworks/vue/src/chat/think-tag-wrap-pattern.ts
index 0cabc8ec..c76a6c44 100644
--- a/packages/frameworks/vue/src/chat/think-tag-wrap-pattern.ts
+++ b/packages/frameworks/vue/src/chat/think-tag-wrap-pattern.ts
@@ -1,4 +1,4 @@
-import { getPartialStartRegString } from "@opentiny/genui-sdk-core";
+import { getPartialStartRegString } from '@opentiny/genui-sdk-core';
export class ThinkTagWrapPattern {
protected thinkStartFlag: string = '';
@@ -18,6 +18,6 @@ export class ThinkTagWrapPattern {
full: this.endRegex,
partial: this.partialEndRegex,
},
- }
+ };
}
}
diff --git a/packages/frameworks/vue/src/config-provider/ConfigProvider.vue b/packages/frameworks/vue/src/config-provider/ConfigProvider.vue
index 7cbf0beb..e3e9f433 100644
--- a/packages/frameworks/vue/src/config-provider/ConfigProvider.vue
+++ b/packages/frameworks/vue/src/config-provider/ConfigProvider.vue
@@ -3,8 +3,9 @@ import { TinyConfigProvider } from '@opentiny/vue';
import { ThemeProvider } from '@opentiny/tiny-robot';
import ThemeTool, { tinyDarkTheme, tinyOldTheme } from '@opentiny/vue-theme/theme-tool';
import { watch, provide, computed, onMounted, ref } from 'vue';
+import type { IMaterials } from '@opentiny/genui-sdk-core';
import { I18nMessages, useI18n } from '../chat/i18n';
-import { GENUI_I18N, GENUI_CONFIG } from '../chat/injection-tokens';
+import { GENUI_I18N, GENUI_CONFIG, GENUI_MATERIALS } from './injection-tokens';
import { useMediaTheme } from './use-media-theme';
export interface ConfigProviderProps {
@@ -12,6 +13,7 @@ export interface ConfigProviderProps {
id?: string;
locale?: string;
i18n?: I18nMessages;
+ materials?: IMaterials;
}
interface IRobotProviderProps {
@@ -59,10 +61,22 @@ const genuiConfig = computed(() => {
provide(GENUI_CONFIG, genuiConfig);
+const internalMaterials = {};
+watch(() => props.materials, (newVal) => {
+ Object.assign(internalMaterials, newVal);
+}, { immediate: true });
+
+provide(
+ GENUI_MATERIALS,
+ internalMaterials,
+);
+
watch(
() => [props.locale, props.i18n] as const,
() => {
- i18n.setLocale(props.locale);
+ if (props.locale && props.locale !== i18n.locale.value) {
+ i18n.setLocale(props.locale);
+ }
props.i18n && i18n.mergeMessages(props.i18n);
},
{ immediate: true },
diff --git a/packages/frameworks/vue/src/config-provider/index.ts b/packages/frameworks/vue/src/config-provider/index.ts
index ea703178..b04735eb 100644
--- a/packages/frameworks/vue/src/config-provider/index.ts
+++ b/packages/frameworks/vue/src/config-provider/index.ts
@@ -1,2 +1,3 @@
export { default as GenuiConfigProvider } from './ConfigProvider.vue';
export * from './use-media-theme';
+export * from './injection-tokens.js';
diff --git a/packages/frameworks/vue/src/config-provider/injection-tokens.ts b/packages/frameworks/vue/src/config-provider/injection-tokens.ts
new file mode 100644
index 00000000..df4d7cb6
--- /dev/null
+++ b/packages/frameworks/vue/src/config-provider/injection-tokens.ts
@@ -0,0 +1,7 @@
+import type { InjectionKey } from 'vue';
+import type { IMaterials } from '@opentiny/genui-sdk-core';
+
+export const GENUI_I18N = Symbol('GENUI_I18N');
+export const GENUI_CONFIG = Symbol('GENUI_CONFIG');
+
+export const GENUI_MATERIALS: InjectionKey = Symbol('GENUI_MATERIALS');
diff --git a/packages/frameworks/vue/src/index.ts b/packages/frameworks/vue/src/index.ts
index 6f4c5fbd..d7cb78e6 100644
--- a/packages/frameworks/vue/src/index.ts
+++ b/packages/frameworks/vue/src/index.ts
@@ -1,4 +1,6 @@
export * from './chat';
export * from './renderer';
export * from './config-provider';
+export * from './legacy-chat';
+export * from './legacy-renderer';
export { RENDERER_SETTINGS_KEY } from '@opentiny/tiny-schema-renderer';
diff --git a/packages/frameworks/vue/src/legacy-chat/GenuiChatWithMaterials.vue b/packages/frameworks/vue/src/legacy-chat/GenuiChatWithMaterials.vue
new file mode 100644
index 00000000..e904fe8d
--- /dev/null
+++ b/packages/frameworks/vue/src/legacy-chat/GenuiChatWithMaterials.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/frameworks/vue/src/legacy-chat/index.ts b/packages/frameworks/vue/src/legacy-chat/index.ts
new file mode 100644
index 00000000..8d3a8299
--- /dev/null
+++ b/packages/frameworks/vue/src/legacy-chat/index.ts
@@ -0,0 +1,8 @@
+export { default as GenuiLegacyChat } from './GenuiChatWithMaterials.vue';
+export * from '../chat/chat.types.js';
+export * from '../config-provider/injection-tokens.js';
+export * from '../chat/i18n/index.js';
+export * from '../chat/tiny-robot-patch/index.js';
+export * from '../chat/event-emitter.js';
+export * from '../chat/chat-utils.js';
+export * from '../chat/think-tag-wrap-pattern.js';
diff --git a/packages/frameworks/vue/src/legacy-renderer/GenuiRendererWithMaterials.vue b/packages/frameworks/vue/src/legacy-renderer/GenuiRendererWithMaterials.vue
new file mode 100644
index 00000000..d4ccd179
--- /dev/null
+++ b/packages/frameworks/vue/src/legacy-renderer/GenuiRendererWithMaterials.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/frameworks/vue/src/legacy-renderer/index.ts b/packages/frameworks/vue/src/legacy-renderer/index.ts
new file mode 100644
index 00000000..008246d5
--- /dev/null
+++ b/packages/frameworks/vue/src/legacy-renderer/index.ts
@@ -0,0 +1,3 @@
+export { default as GenuiLegacyRenderer } from './GenuiRendererWithMaterials.vue';
+export * from '../renderer/config.js';
+export * from '../renderer/renderer.types.js';
diff --git a/packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue b/packages/frameworks/vue/src/renderer/GenuiRenderer.vue
similarity index 59%
rename from packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue
rename to packages/frameworks/vue/src/renderer/GenuiRenderer.vue
index 6b48332e..45f031b8 100644
--- a/packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue
+++ b/packages/frameworks/vue/src/renderer/GenuiRenderer.vue
@@ -1,11 +1,10 @@
diff --git a/packages/frameworks/vue/src/renderer/config.ts b/packages/frameworks/vue/src/renderer/config.ts
index 1cbcf22e..6687543f 100644
--- a/packages/frameworks/vue/src/renderer/config.ts
+++ b/packages/frameworks/vue/src/renderer/config.ts
@@ -1,5 +1,5 @@
export const requiredCompleteFieldSelectors = [
- '[componentName=Img] > props > src',
+ '[componentName=img] > props > src',
'componentName',
'style',
'[componentName=Page] > css',
@@ -8,15 +8,5 @@ export const requiredCompleteFieldSelectors = [
'[type=JSSlot][value=]',
'type',
':empty:object',
- '[componentName=TinyTabItem] > props > name',
- '[componentName=TinyTransfer] > props > data',
- '[componentName=TinyNumeric] > props > controlsPosition',
- '[componentName=TinyNumeric] > props > modelValue',
- '[componentName^=TinyChart] > props > :string',
- '[componentName=TinyChartPie] > props > data > rows > *',
- '[componentName=TinyForm] > props > labelPosition',
- '[componentName=TinyRadioGroup] > props > options > * > label',
- // ng element version
- '[componentName=img] > props > src',
- '[componentName] > props > ngModel',
+ '[componentName] > props > ref',
];
diff --git a/packages/frameworks/vue/src/renderer/index.ts b/packages/frameworks/vue/src/renderer/index.ts
index 3074b9ab..1fa4840f 100644
--- a/packages/frameworks/vue/src/renderer/index.ts
+++ b/packages/frameworks/vue/src/renderer/index.ts
@@ -1,3 +1,3 @@
-export { default as GenuiRenderer } from './SchemaCardRenderer.vue';
+export { default as GenuiRenderer } from './GenuiRenderer.vue';
export * from './config.js'
export * from './renderer.types.js';
diff --git a/packages/frameworks/vue/src/renderer/renderer.types.ts b/packages/frameworks/vue/src/renderer/renderer.types.ts
index 636d3048..b780b866 100644
--- a/packages/frameworks/vue/src/renderer/renderer.types.ts
+++ b/packages/frameworks/vue/src/renderer/renderer.types.ts
@@ -1,12 +1,16 @@
import type { Component, VNode } from 'vue';
-import type { CardSchema } from '@opentiny/genui-sdk-core';
+import type { CardSchema, IGenPromptAction } from '@opentiny/genui-sdk-core';
+
+export interface ICustomAction extends Partial {
+ execute: (params: any, context: Record) => any;
+}
export interface IRendererProps {
content: string | { [prop: string]: any };
generating?: boolean;
isJsonComplete?: boolean;
customComponents?: Record;
- customActions?: any;
+ customActions?: Record;
requiredCompleteFieldSelectors?: string[];
id?: string;
state?: Record;
diff --git a/packages/frameworks/vue/vite.config.ts b/packages/frameworks/vue/vite.config.ts
index 95f10944..d685496d 100644
--- a/packages/frameworks/vue/vite.config.ts
+++ b/packages/frameworks/vue/vite.config.ts
@@ -23,8 +23,6 @@ export default defineConfig(({ mode }) => {
dts({
rollupTypes: true,
bundledPackages: [
- '@opentiny/genui-sdk-core',
- '@opentiny/genui-sdk-materials-vue-opentiny-vue',
'@opentiny/tiny-schema-renderer',
'zod',
'zod-to-json-schema',
@@ -45,15 +43,17 @@ export default defineConfig(({ mode }) => {
entry: {
index: path.resolve(__dirname, './src/index.ts'),
chat: path.resolve(__dirname, './src/chat/index.ts'),
+ 'legacy-chat': path.resolve(__dirname, './src/legacy-chat/index.ts'),
renderer: path.resolve(__dirname, './src/renderer/index.ts'),
+ 'legacy-renderer': path.resolve(__dirname, './src/legacy-renderer/index.ts'),
'config-provider': path.resolve(__dirname, './src/config-provider/index.ts'),
'transform-jsx': path.resolve(__dirname, './src/transform-jsx.ts'),
},
formats: ['es'],
fileName: (_, entryName) => `${entryName}.js`,
},
- outDir: path.resolve(__dirname, './output/dist'),
- sourcemap: false,
+ outDir: path.resolve(__dirname, './dist'),
+ sourcemap: true,
terserOptions: {
mangle: {
toplevel: true,
diff --git a/packages/materials/angular-opentiny-ng/README.md b/packages/materials/angular-opentiny-ng/README.md
new file mode 100644
index 00000000..46d4ca53
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/README.md
@@ -0,0 +1,59 @@
+# @opentiny/genui-sdk-materials-angular-opentiny-ng
+
+
+A GenUI Angular materials package based on [OpenTiny NG](https://opentiny.design/tiny-ng/), providing materials metadata for schema-driven page generation.
+
+## Install
+
+```bash
+npm install @opentiny/genui-sdk-materials-angular-opentiny-ng @opentiny/genui-sdk-core
+```
+
+## Quick Start
+
+### Generate LLM Prompt (Server)
+
+```ts
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/meta';
+
+const systemPrompt = genPrompt('Angular', materialsMeta, customConfig);
+```
+
+`materialsMeta.wrapperComponent` defaults to `TiCard`.
+
+### Default Props (Angular ConfigProvider)
+
+Pass `materialsMeta` via `rendererConfig` so the renderer can derive component default props:
+
+```ts
+import { materialsMeta } from '@opentiny/genui-sdk-materials-angular-opentiny-ng/meta';
+```
+
+```html
+
+
+
+```
+
+## API
+
+| Export Path | Exports | Description |
+|-------------|---------|-------------|
+| `@opentiny/genui-sdk-materials-angular-opentiny-ng` | `materialsMeta` | Unified entry |
+| `.../meta` | `materialsMeta` | For `genPrompt()` / building the server system prompt |
+
+### `materialsMeta`
+
+Materials metadata, including:
+
+- `materials`: Protocol descriptions for components / blocks / snippets
+- `wrapperComponent`: Default wrapper component (`TiCard`)
+- `whiteList`: Whitelist of `componentName` values available to the LLM
+- `examples`: Prompt example schemas
+
+Component library: `@opentiny/ng`.
+
+## More
+
+- [GenUI SDK](https://opentiny.design/genui-sdk)
diff --git a/packages/materials/angular-opentiny-ng/package.json b/packages/materials/angular-opentiny-ng/package.json
index d8c08617..e2ab7d15 100644
--- a/packages/materials/angular-opentiny-ng/package.json
+++ b/packages/materials/angular-opentiny-ng/package.json
@@ -1,25 +1,59 @@
{
"name": "@opentiny/genui-sdk-materials-angular-opentiny-ng",
"version": "0.0.1",
+ "description": "GenUI Angular materials package based on OpenTiny NG",
+ "author": "OpenTiny Team",
+ "license": "MIT",
+ "homepage": "https://opentiny.design/genui-sdk",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/opentiny/genui-sdk",
+ "directory": "packages/materials/angular-opentiny-ng"
+ },
+ "bugs": {
+ "url": "https://github.com/opentiny/genui-sdk/issues"
+ },
+ "keywords": [
+ "genui",
+ "generative-ui",
+ "opentiny",
+ "angular",
+ "materials"
+ ],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
+ "files": [
+ "dist",
+ "README.md"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
"exports": {
".": {
- "import": "./dist/index.js",
"types": "./dist/index.d.ts",
+ "import": "./dist/index.js",
"require": "./dist/index.js"
},
- "./render-config": {
- "import": "./dist/render-config.js",
- "types": "./dist/render-config.d.ts",
- "require": "./dist/render-config.js"
+ "./meta": {
+ "types": "./dist/meta.d.ts",
+ "import": "./dist/meta.js",
+ "require": "./dist/meta.js"
+ },
+ "./materials": {
+ "types": "./dist/materials.d.ts",
+ "import": "./dist/materials.js",
+ "require": "./dist/materials.js"
}
},
"scripts": {
"build": "vite build"
},
"dependencies": {
+ "@angular/core": "^20.3.0",
+ "@opentiny/ng": "^1.0.3",
+ "@opentiny/genui-sdk-core": "workspace:*"
},
"devDependencies": {
"escape-string-regexp": "^1.0.5",
diff --git a/packages/materials/angular-opentiny-ng/src/index.ts b/packages/materials/angular-opentiny-ng/src/index.ts
index 583f7175..47ef1e6c 100644
--- a/packages/materials/angular-opentiny-ng/src/index.ts
+++ b/packages/materials/angular-opentiny-ng/src/index.ts
@@ -1 +1,2 @@
-export * from './render-config';
+export * from './meta';
+export * from './materials';
diff --git a/packages/materials/angular-opentiny-ng/src/materials/components/index.ts b/packages/materials/angular-opentiny-ng/src/materials/components/index.ts
new file mode 100644
index 00000000..e3319de0
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/materials/components/index.ts
@@ -0,0 +1 @@
+export * from './ng-components';
diff --git a/packages/materials/angular-opentiny-ng/src/materials/components/ng-components.ts b/packages/materials/angular-opentiny-ng/src/materials/components/ng-components.ts
new file mode 100644
index 00000000..986a7f60
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/materials/components/ng-components.ts
@@ -0,0 +1,101 @@
+import { Type } from '@angular/core';
+import {
+ TiButtonComponent,
+ TiButtonModule,
+ TiSelectComponent,
+ TiSelectModule,
+ TiTextComponent,
+ TiTextModule,
+ TiTableComponent,
+ TiTableModule,
+ TiModalComponent,
+ TiModalModule,
+ TiDateComponent,
+ TiDateModule,
+ TiPaginationComponent,
+ TiPaginationModule,
+ TiTabsComponent,
+ TiTabModule,
+ TiCheckboxComponent,
+ TiCheckboxModule,
+ TiCheckboxGroupComponent,
+ TiRadioComponent,
+ TiRadioModule,
+ TiRadioGroupComponent,
+ TiTabComponent,
+ TiSwitchComponent,
+ TiSwitchModule,
+ TiCardComponent,
+ TiCardModule,
+ TiUploadComponent,
+ TiUploadModule,
+ TiFormfieldComponent,
+ TiFormfieldModule,
+ TiCardHeaderComponent,
+ TiItemComponent,
+ TiDateRangeComponent,
+ TiDateRangeModule,
+ TiSliderComponent,
+ TiSliderModule,
+ TiRateComponent,
+ TiRateModule,
+ TiTextareaComponent,
+ TiTextareaModule,
+} from '@opentiny/ng';
+
+(TiTextComponent['ɵcmp'] as any).selectors[0][0] = 'input';
+(TiTextareaComponent['ɵcmp'] as any).selectors[0][0] = 'textarea';
+(TiRadioComponent['ɵcmp'] as any).selectors[0][0] = 'input';
+(TiCheckboxComponent['ɵcmp'] as any).selectors[0][0] = 'input';
+
+export const components: Record> = {
+ TiButton: TiButtonComponent,
+ TiSelect: TiSelectComponent,
+ TiText: TiTextComponent,
+ TiTable: TiTableComponent,
+ TiModal: TiModalComponent,
+ TiDate: TiDateComponent,
+ TiPagination: TiPaginationComponent,
+ TiTabs: TiTabsComponent,
+ TiTab: TiTabComponent,
+ TiCheckbox: TiCheckboxComponent,
+ TiCheckboxGroup: TiCheckboxGroupComponent,
+ TiRadio: TiRadioComponent,
+ TiRadioGroup: TiRadioGroupComponent,
+ TiSwitch: TiSwitchComponent,
+ TiCard: TiCardComponent,
+ TiUpload: TiUploadComponent,
+ TiFormField: TiFormfieldComponent,
+ TiCardHeader: TiCardHeaderComponent,
+ TiItem: TiItemComponent,
+ TiDateRange: TiDateRangeComponent,
+ TiSlider: TiSliderComponent,
+ TiRate: TiRateComponent,
+ TiTextArea: TiTextareaComponent,
+};
+
+export const modules: Record> = {
+ TiButton: TiButtonModule,
+ TiSelect: TiSelectModule,
+ TiText: TiTextModule,
+ TiTable: TiTableModule,
+ TiModal: TiModalModule,
+ TiDate: TiDateModule,
+ TiPagination: TiPaginationModule,
+ TiTabs: TiTabModule,
+ TiTab: TiTabModule,
+ TiCheckbox: TiCheckboxModule,
+ TiCheckboxGroup: TiCheckboxModule,
+ TiRadio: TiRadioModule,
+ TiRadioGroup: TiRadioModule,
+ TiSwitch: TiSwitchModule,
+ TiCard: TiCardModule,
+ TiUpload: TiUploadModule,
+ TiFormField: TiFormfieldModule,
+ TiCardHeader: TiCardModule,
+ TiItem: TiFormfieldModule,
+ TiDateRange: TiDateRangeModule,
+ TiSlider: TiSliderModule,
+ TiRate: TiRateModule,
+ TiTextArea: TiTextareaModule,
+};
diff --git a/packages/materials/angular-opentiny-ng/src/materials/directives/index.ts b/packages/materials/angular-opentiny-ng/src/materials/directives/index.ts
new file mode 100644
index 00000000..47965627
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/materials/directives/index.ts
@@ -0,0 +1 @@
+export * from './ng-directives';
diff --git a/packages/materials/angular-opentiny-ng/src/materials/directives/ng-directives.ts b/packages/materials/angular-opentiny-ng/src/materials/directives/ng-directives.ts
new file mode 100644
index 00000000..a3c268b7
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/materials/directives/ng-directives.ts
@@ -0,0 +1,9 @@
+import { Type } from '@angular/core';
+import { TiTipDirective } from '@opentiny/ng';
+import type { AutoApplyDirectivePattern } from '../materials';
+
+export const directives: Record> = {
+ TiTip: TiTipDirective,
+};
+
+export const autoApplyDirectives: AutoApplyDirectivePattern = {};
diff --git a/packages/materials/angular-opentiny-ng/src/materials/index.ts b/packages/materials/angular-opentiny-ng/src/materials/index.ts
new file mode 100644
index 00000000..ea409aff
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/materials/index.ts
@@ -0,0 +1 @@
+export * from './materials';
diff --git a/packages/materials/angular-opentiny-ng/src/materials/materials.ts b/packages/materials/angular-opentiny-ng/src/materials/materials.ts
new file mode 100644
index 00000000..547d928d
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/materials/materials.ts
@@ -0,0 +1,24 @@
+import type { Type } from '@angular/core';
+import { buildMaterialDefaultValueMap, type IMaterials } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '../meta';
+import { autoApplyDirectives, directives } from './directives';
+import { components, modules } from './components';
+
+export type AutoApplyDirectivePattern = Record<
+ string,
+ (schema: any, context?: Record) => boolean
+>;
+
+export interface INgMaterials extends IMaterials {
+ modules?: Record>;
+ directives?: Record>;
+ autoApplyDirectives?: AutoApplyDirectivePattern;
+}
+
+export const materials: INgMaterials = {
+ components,
+ modules,
+ directives,
+ autoApplyDirectives,
+ defaultPropsMap: buildMaterialDefaultValueMap(materialsMeta),
+};
diff --git a/packages/materials/angular-opentiny-ng/src/meta/example-schema.ts b/packages/materials/angular-opentiny-ng/src/meta/example-schema.ts
new file mode 100644
index 00000000..3df26cbe
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/example-schema.ts
@@ -0,0 +1,14 @@
+import type { IExample } from '@opentiny/genui-sdk-core';
+import formSchema from './examples/form.json' with { type: 'json' };
+import infoCardSchema from './examples/info.json' with { type: 'json' };
+import gridSchema from './examples/grid.json' with { type: 'json' };
+import tabsSchema from './examples/tabs.json' with { type: 'json' };
+import paginationSchema from './examples/pagination.json' with { type: 'json' };
+
+export const examples = [
+ { id: 'form', name: '双向绑定的表单', schema: formSchema },
+ { id: 'info', name: '信息展示卡片', schema: infoCardSchema },
+ { id: 'grid', name: '表格卡片', schema: gridSchema },
+ { id: 'tabs', name: 'Tabs卡片', schema: tabsSchema },
+ { id: 'pagination', name: '分页表格', schema: paginationSchema },
+] as IExample[];
diff --git a/packages/materials/angular-opentiny-ng/src/meta/examples/form.json b/packages/materials/angular-opentiny-ng/src/meta/examples/form.json
new file mode 100644
index 00000000..816f5971
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/examples/form.json
@@ -0,0 +1,249 @@
+{
+ "state": {
+ "formData": {
+ "name": "张三",
+ "sex": "男",
+ "department": "HR",
+ "protocolStart": "2023-01-01",
+ "email": ""
+ }
+ },
+ "methods": {
+ "departChange": {
+ "type": "JSFunction",
+ "value": "function departChange(value) { console.log(value) }"
+ },
+ "handleSubmit": {
+ "type": "JSFunction",
+ "value": "function handleSubmit() { console.log(this.state.formData) }"
+ }
+ },
+ "componentName": "Page",
+ "props": {
+ "style": "width: 414px;"
+ },
+ "children": [
+ {
+ "componentName": "h3",
+ "props": {},
+ "children": "更新员工信息"
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 16px;"
+ },
+ "children": [
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 8px;"
+ },
+ "children": [
+ {
+ "componentName": "label",
+ "props": {
+ "style": "font-weight: bold;"
+ },
+ "children": "姓名"
+ },
+ {
+ "componentName": "TiText",
+ "props": {
+ "placeholder": "请输入",
+ "ngModel": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.name"
+ }
+ },
+ "directives": [
+ {
+ "directiveName": "ngModel"
+ },
+ {
+ "directiveName": "defaultValueAccessor"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 8px;"
+ },
+ "children": [
+ {
+ "componentName": "label",
+ "props": {
+ "style": "font-weight: bold;"
+ },
+ "children": "工号"
+ },
+ {
+ "componentName": "TiText",
+ "props": {
+ "disabled": true,
+ "ngModel": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.id"
+ }
+ },
+ "directives": [
+ {
+ "directiveName": "ngModel"
+ },
+ {
+ "directiveName": "defaultValueAccessor"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 8px;"
+ },
+ "children": [
+ {
+ "componentName": "label",
+ "props": {
+ "style": "font-weight: bold;"
+ },
+ "children": "性别"
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; gap: 16px;"
+ },
+ "children": [
+ {
+ "componentName": "TiRadio",
+ "props": {
+ "value": "男",
+ "label": "男"
+ }
+ },
+ {
+ "componentName": "TiRadio",
+ "props": {
+ "value": "女",
+ "label": "女"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 8px;"
+ },
+ "children": [
+ {
+ "componentName": "label",
+ "props": {
+ "style": "font-weight: bold;"
+ },
+ "children": "部门"
+ },
+ {
+ "componentName": "TiSelect",
+ "props": {
+ "placeholder": "请选择",
+ "ngModel": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.department"
+ },
+ "options": [
+ {
+ "value": "HR",
+ "label": "人事部"
+ },
+ {
+ "value": "other",
+ "label": "其他部门"
+ }
+ ],
+ "ngModelChange": {
+ "type": "JSExpression",
+ "value": "this.departChange"
+ }
+ },
+ "directives": [
+ {
+ "directiveName": "ngModel"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 8px;"
+ },
+ "children": [
+ {
+ "componentName": "label",
+ "props": {
+ "style": "font-weight: bold;"
+ },
+ "children": "入职日期"
+ },
+ {
+ "componentName": "TiDate",
+ "props": {
+ "placeholder": "请选择日期",
+ "disabled": true,
+ "ngModel": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.protocolStart"
+ },
+ "format": "yyyy-MM-dd"
+ },
+ "directives": [
+ {
+ "directiveName": "ngModel"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; gap: 8px; margin-top: 16px;"
+ },
+ "children": [
+ {
+ "componentName": "TiButton",
+ "props": {
+ "type": "primary",
+ "onClick": {
+ "type": "JSExpression",
+ "value": "this.handleSubmit"
+ }
+ },
+ "children": "确认"
+ },
+ {
+ "componentName": "TiButton",
+ "props": {
+ "type": "default"
+ },
+ "children": "取消"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/angular-opentiny-ng/src/meta/examples/grid.json b/packages/materials/angular-opentiny-ng/src/meta/examples/grid.json
new file mode 100644
index 00000000..05465457
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/examples/grid.json
@@ -0,0 +1,254 @@
+{
+ "componentName": "Page",
+ "css": ".page-base-style {padding: 24px;background: #FFFFFF;}.block-base-style {margin: 16px;}.component-base-style {margin: 8px;}",
+ "props": {
+ "className": "page-base-style"
+ },
+ "lifeCycles": {},
+ "children": [
+ {
+ "componentName": "TiTable",
+ "props": {
+ "srcData": {
+ "type": "JSExpression",
+ "value": "this.state.srcData"
+ },
+ "displayedData": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.displayedData"
+ },
+ "columns": {
+ "type": "JSExpression",
+ "value": "this.state.columns"
+ },
+ "className": "component-base-style"
+ },
+ "children": [
+ {
+ "componentName": "table",
+ "children": [
+ {
+ "componentName": "thead",
+ "children": [
+ {
+ "componentName": "tr",
+ "children": [
+ {
+ "componentName": "th",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "column.title"
+ }
+ }
+ }
+ ],
+ "loop": {
+ "type": "JSExpression",
+ "value": "this.state.columns"
+ },
+ "loopArgs": [
+ "column"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "tbody",
+ "children": [
+ {
+ "componentName": "tr",
+ "loop": {
+ "type": "JSExpression",
+ "value": "this.state.displayedData"
+ },
+ "loopArgs": [
+ "row"
+ ],
+ "children": [
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.name"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.id"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.sex"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.department"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.protocolStart"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.email"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "TinyButton",
+ "props": {
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { this.deleteRow(row) }"
+ }
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "`删除${row.name}`"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "state": {
+ "columns": [
+ {
+ "field": "name",
+ "title": "姓名"
+ },
+ {
+ "field": "id",
+ "title": "工号"
+ },
+ {
+ "field": "sex",
+ "title": "性别"
+ },
+ {
+ "field": "department",
+ "title": "部门"
+ },
+ {
+ "field": "protocolStart",
+ "title": "入职日期"
+ },
+ {
+ "field": "email",
+ "title": "邮箱"
+ },
+ {
+ "field": "actions",
+ "title": "操作"
+ }
+ ],
+ "srcData": [
+ {
+ "name": "李四",
+ "id": "2",
+ "sex": "女",
+ "department": "技术部",
+ "protocolStart": "2019-05-15",
+ "email": "lisi@test.com"
+ },
+ {
+ "name": "王五",
+ "id": "3",
+ "sex": "男",
+ "department": "市场部",
+ "protocolStart": "2020-03-20",
+ "email": "wangwu@test.com"
+ }
+ ],
+ "displayedData": []
+ },
+ "methods": {
+ "deleteRow": {
+ "type": "JSFunction",
+ "value": "function(row) { this.state.srcData = this.state.srcData.filter(item => item.id !== row.id) }"
+ }
+ },
+ "dataSource": {
+ "list": []
+ },
+ "id": "body"
+}
diff --git a/packages/materials/angular-opentiny-ng/src/meta/examples/info.json b/packages/materials/angular-opentiny-ng/src/meta/examples/info.json
new file mode 100644
index 00000000..2fbdf7da
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/examples/info.json
@@ -0,0 +1,87 @@
+{
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "h3",
+ "props": {
+ "style": "font-size: 14px;font-weight: bold;line-height:2;margin-bottom:20px;display:block;"
+ },
+ "children": "员工信息详情"
+ },
+ {
+ "componentName": "TiCard",
+ "props": {
+ "header": "员工信息",
+ "style": "width: 374px;"
+ },
+ "children": [
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; flex-direction: column; gap: 16px; padding: 20px;"
+ },
+ "children": [
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex;"
+ },
+ "children": [
+ {
+ "componentName": "span",
+ "props": {
+ "style": "width: 80px; font-weight: bold;"
+ },
+ "children": "姓名"
+ },
+ {
+ "componentName": "span",
+ "children": "张三"
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex;"
+ },
+ "children": [
+ {
+ "componentName": "span",
+ "props": {
+ "style": "width: 80px; font-weight: bold;"
+ },
+ "children": "电话"
+ },
+ {
+ "componentName": "span",
+ "children": "18856254558"
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex;"
+ },
+ "children": [
+ {
+ "componentName": "span",
+ "props": {
+ "style": "width: 80px; font-weight: bold;"
+ },
+ "children": "部门"
+ },
+ {
+ "componentName": "span",
+ "children": "HR"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "id": "body"
+}
diff --git a/packages/materials/angular-opentiny-ng/src/meta/examples/pagination.json b/packages/materials/angular-opentiny-ng/src/meta/examples/pagination.json
new file mode 100644
index 00000000..09ab2a99
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/examples/pagination.json
@@ -0,0 +1,210 @@
+{
+ "componentName": "Page",
+ "props": {
+ "className": "page-base-style"
+ },
+ "css": ".page-base-style {padding: 24px;background: #FFFFFF;}",
+ "children": [
+ {
+ "componentName": "TiTable",
+ "props": {
+ "srcData": {
+ "type": "JSExpression",
+ "value": "this.state.srcData"
+ },
+ "displayedData": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.displayedData"
+ },
+ "columns": {
+ "type": "JSExpression",
+ "value": "this.state.columns"
+ }
+ },
+ "children": [
+ {
+ "componentName": "table",
+ "children": [
+ {
+ "componentName": "thead",
+ "children": [
+ {
+ "componentName": "tr",
+ "children": [
+ {
+ "componentName": "th",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "column.title"
+ }
+ }
+ }
+ ],
+ "loop": {
+ "type": "JSExpression",
+ "value": "this.state.columns"
+ },
+ "loopArgs": [
+ "column"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "tbody",
+ "children": [
+ {
+ "componentName": "tr",
+ "children": [
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.id"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.name"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.department"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "td",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.email"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "loop": {
+ "type": "JSExpression",
+ "value": "this.state.displayedData"
+ },
+ "loopArgs": [
+ "row"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TiPagination",
+ "props": {
+ "currentPage": {
+ "type": "JSExpression",
+ "value": "this.state.currentPage"
+ },
+ "pageSize": {
+ "type": "JSExpression",
+ "value": "this.state.pageSize"
+ },
+ "total": {
+ "type": "JSExpression",
+ "value": "this.state.total"
+ },
+ "currentPageChange": {
+ "type": "JSFunction",
+ "value": "function(page) { this.state.currentPage = page }"
+ },
+ "pageSizeChange": {
+ "type": "JSFunction",
+ "value": "function(size) { this.state.pageSize = size }"
+ }
+ }
+ }
+ ],
+ "state": {
+ "currentPage": 1,
+ "pageSize": 10,
+ "total": 100,
+ "columns": [
+ {
+ "field": "id",
+ "title": "ID"
+ },
+ {
+ "field": "name",
+ "title": "姓名"
+ },
+ {
+ "field": "department",
+ "title": "部门"
+ },
+ {
+ "field": "email",
+ "title": "邮箱"
+ }
+ ],
+ "srcData": {
+ "data": [
+ {
+ "id": "1",
+ "name": "张三",
+ "department": "HR",
+ "email": "zhangsan@test.com"
+ },
+ {
+ "id": "2",
+ "name": "李四",
+ "department": "技术部",
+ "email": "lisi@test.com"
+ },
+ {
+ "id": "3",
+ "name": "王五",
+ "department": "市场部",
+ "email": "wangwu@test.com"
+ }
+ ]
+ },
+ "displayedData": []
+ },
+ "id": "body"
+}
diff --git a/packages/materials/angular-opentiny-ng/src/meta/examples/tabs.json b/packages/materials/angular-opentiny-ng/src/meta/examples/tabs.json
new file mode 100644
index 00000000..17e29ddb
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/examples/tabs.json
@@ -0,0 +1,249 @@
+{
+ "componentName": "Page",
+ "fileName": "Untitled",
+ "css": ".page-base-style {\n padding: 24px;background: #FFFFFF;\n}\n\n.block-base-style {\n margin: 16px;\n}\n\n.component-base-style {\n margin: 8px;\n}\n",
+ "props": {
+ "className": "page-base-style"
+ },
+ "lifeCycles": {},
+ "children": [
+ {
+ "componentName": "div",
+ "id": "e9a7b6c5",
+ "props": {
+ "style": "display: flex; flex-direction: column; align-items: center;"
+ },
+ "children": [
+ {
+ "componentName": "h2",
+ "id": "f2g3h4i5",
+ "props": {
+ "style": "font-size: 24px; font-weight: bold; margin-bottom: 20px;"
+ },
+ "children": "降本增效,加速企业数字化转型"
+ },
+ {
+ "componentName": "TiTabs",
+ "id": "j6k7l8m9",
+ "props": {
+ "className": "component-base-style"
+ },
+ "children": [
+ {
+ "componentName": "TiTab",
+ "id": "n0o1p2q3",
+ "props": {
+ "header": "精选推荐",
+ "id": "tab1",
+ "active": true
+ },
+ "children": [
+ {
+ "componentName": "div",
+ "id": "r4s5t6u7",
+ "props": {
+ "style": "display: flex; flex-wrap: wrap; justify-content: space-around; gap: 20px; padding: 20px;"
+ },
+ "children": [
+ {
+ "componentName": "div",
+ "id": "v8w9x0y1",
+ "props": {
+ "style": "width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"
+ },
+ "children": [
+ {
+ "componentName": "img",
+ "id": "z2a3b4c5",
+ "props": {
+ "src": "https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/Domains.png",
+ "alt": "域名注册服务",
+ "style": "width: 60px; height: 60px; margin-bottom: 10px;"
+ }
+ },
+ {
+ "componentName": "h4",
+ "id": "d6e7f8g9",
+ "props": {
+ "style": "font-size: 16px; font-weight: bold; margin-bottom: 5px;"
+ },
+ "children": "域名注册服务"
+ },
+ {
+ "componentName": "p",
+ "id": "h0i1j2k3",
+ "props": {
+ "style": "font-size: 14px; color: #666;"
+ },
+ "children": "适用于网站建设、域名投资等场景"
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "id": "l4m5n6o7",
+ "props": {
+ "style": "width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"
+ },
+ "children": [
+ {
+ "componentName": "img",
+ "id": "p8q9r0s1",
+ "props": {
+ "src": "https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/mail0918.png",
+ "alt": "华为云企业邮箱",
+ "style": "width: 60px; height: 60px; margin-bottom: 10px;"
+ }
+ },
+ {
+ "componentName": "h4",
+ "id": "t2u3v4w5",
+ "props": {
+ "style": "font-size: 16px; font-weight: bold; margin-bottom: 5px;"
+ },
+ "children": "华为云企业邮箱"
+ },
+ {
+ "componentName": "p",
+ "id": "x6y7z8a9",
+ "props": {
+ "style": "font-size: 14px; color: #666;"
+ },
+ "children": "免费试用,无限容量,全球畅邮"
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "id": "b0c1d2e3",
+ "props": {
+ "style": "width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"
+ },
+ "children": [
+ {
+ "componentName": "img",
+ "id": "f4g5h6i7",
+ "props": {
+ "src": "https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/Cloudsite.png",
+ "alt": "企业门户(原云速建站)",
+ "style": "width: 60px; height: 60px; margin-bottom: 10px;"
+ }
+ },
+ {
+ "componentName": "h4",
+ "id": "j8k9l0m1",
+ "props": {
+ "style": "font-size: 16px; font-weight: bold; margin-bottom: 5px;"
+ },
+ "children": "企业门户(原云速建站)"
+ },
+ {
+ "componentName": "p",
+ "id": "n2o3p4q5",
+ "props": {
+ "style": "font-size: 14px; color: #666;"
+ },
+ "children": "无需代码,一键拖拽,3000+模板随心选"
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "id": "r6s7t8u9",
+ "props": {
+ "style": "width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"
+ },
+ "children": [
+ {
+ "componentName": "img",
+ "id": "v0w1x2y3",
+ "props": {
+ "src": "https://res-static.hc-cdn.cn/cloudbu-site/china/zh-cn/yunying/new-home/markplace/home_icon_14.svg",
+ "alt": "财税卫士",
+ "style": "width: 60px; height: 60px; margin-bottom: 10px;"
+ }
+ },
+ {
+ "componentName": "h4",
+ "id": "z4a5b6c7",
+ "props": {
+ "style": "font-size: 16px; font-weight: bold; margin-bottom: 5px;"
+ },
+ "children": "财税卫士"
+ },
+ {
+ "componentName": "p",
+ "id": "d8e9f0g1",
+ "props": {
+ "style": "font-size: 14px; color: #666;"
+ },
+ "children": "智能财税风控检测软件,助力企业合规"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TiTab",
+ "id": "h2i3j4k5",
+ "props": {
+ "header": "企业初创",
+ "id": "tab2"
+ },
+ "children": []
+ },
+ {
+ "componentName": "TiTab",
+ "id": "l6m7n8o9",
+ "props": {
+ "header": "企业营销",
+ "id": "tab3"
+ },
+ "children": []
+ },
+ {
+ "componentName": "TiTab",
+ "id": "p0q1r2s3",
+ "props": {
+ "header": "企业办公",
+ "id": "tab4"
+ },
+ "children": []
+ }
+ ]
+ },
+ {
+ "componentName": "div",
+ "id": "t4u5v6w7",
+ "props": {
+ "style": "text-align: center; margin-top: 20px;"
+ },
+ "children": [
+ {
+ "componentName": "a",
+ "id": "x8y9z0a1",
+ "props": {
+ "style": "font-size: 16px; color: #1890ff; text-decoration: none;",
+ "href": "#"
+ },
+ "children": "查看企业应用中心 >"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "dataSource": {
+ "list": []
+ },
+ "methods": {},
+ "bridge": {
+ "imports": []
+ },
+ "state": {},
+ "inputs": [],
+ "outputs": [],
+ "id": "body"
+}
diff --git a/packages/materials/angular-opentiny-ng/src/meta/index.ts b/packages/materials/angular-opentiny-ng/src/meta/index.ts
new file mode 100644
index 00000000..c9942f46
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/index.ts
@@ -0,0 +1 @@
+export * from './meta';
diff --git a/packages/materials/angular-opentiny-ng/src/render-config/bundle.json b/packages/materials/angular-opentiny-ng/src/meta/materials/bundle.json
similarity index 97%
rename from packages/materials/angular-opentiny-ng/src/render-config/bundle.json
rename to packages/materials/angular-opentiny-ng/src/meta/materials/bundle.json
index 1d307544..0a4ae31f 100644
--- a/packages/materials/angular-opentiny-ng/src/render-config/bundle.json
+++ b/packages/materials/angular-opentiny-ng/src/meta/materials/bundle.json
@@ -88,7 +88,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "default",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -125,7 +124,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "middle",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -166,7 +164,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -189,7 +186,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -216,7 +212,6 @@
{
"name": "event",
"type": "Event",
- "defaultValue": "",
"description": {
"zh_CN": "原生事件对象"
}
@@ -360,7 +355,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -383,7 +377,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -406,7 +399,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "medium",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -469,7 +461,6 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前输入值"
}
@@ -492,7 +483,6 @@
{
"name": "event",
"type": "FocusEvent",
- "defaultValue": "",
"description": {
"zh_CN": "焦点事件对象"
}
@@ -515,7 +505,6 @@
{
"name": "event",
"type": "FocusEvent",
- "defaultValue": "",
"description": {
"zh_CN": "焦点事件对象"
}
@@ -653,8 +642,6 @@
"cols": 12,
"labelPosition": "left",
"type": "array",
- "defaultValue": [
- ],
"widget": {
"component": "ArrayConfigurator",
"props": {
@@ -699,7 +686,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -722,7 +708,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -745,7 +730,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "medium",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -786,7 +770,6 @@
{
"name": "displayedData",
"type": "any[]",
- "defaultValue": "",
"description": {
"zh_CN": "当前显示的表格数据数组"
}
@@ -809,7 +792,6 @@
{
"name": "tableComponent",
"type": "TiTableComponent",
- "defaultValue": "",
"description": {
"zh_CN": "表格组件实例,可通过 getDataState() 方法获取当前数据状态"
}
@@ -931,7 +913,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -954,7 +935,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "50%",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -977,7 +957,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": true,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1000,7 +979,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": true,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1216,7 +1194,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1239,7 +1216,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1262,7 +1238,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1289,7 +1264,6 @@
{
"name": "value",
"type": "any",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中的值"
}
@@ -1312,7 +1286,6 @@
{
"name": "visible",
"type": "boolean",
- "defaultValue": "",
"description": {
"zh_CN": "是否显示"
}
@@ -1456,7 +1429,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "yyyy-MM-dd",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -1479,7 +1451,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1502,7 +1473,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": true,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -1529,7 +1499,6 @@
{
"name": "value",
"type": "Date",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中的日期"
}
@@ -1629,7 +1598,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 1,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -1652,7 +1620,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 10,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -1675,7 +1642,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 0,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -1698,12 +1664,6 @@
"cols": 12,
"labelPosition": "left",
"type": "array",
- "defaultValue": [
- 10,
- 20,
- 50,
- 100
- ],
"widget": {
"component": "ArrayConfigurator",
"props": {
@@ -1726,7 +1686,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "prev, pager, next, jumper, ->, total",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -1753,7 +1712,6 @@
{
"name": "currentPage",
"type": "number",
- "defaultValue": "",
"description": {
"zh_CN": "当前页码"
}
@@ -1776,7 +1734,6 @@
{
"name": "pageSize",
"type": "number",
- "defaultValue": "",
"description": {
"zh_CN": "每页条数"
}
@@ -1875,7 +1832,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "100px",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -1898,7 +1854,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "right",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -1959,7 +1914,6 @@
{
"name": "tab",
"type": "TiTabComponent",
- "defaultValue": "",
"description": {
"zh_CN": "页签组件实例"
}
@@ -2103,7 +2057,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2126,7 +2079,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2153,7 +2105,6 @@
{
"name": "active",
"type": "boolean",
- "defaultValue": false,
"description": {
"zh_CN": "当前页签是否为激活状态"
}
@@ -2277,7 +2228,6 @@
"cols": 12,
"labelPosition": "left",
"type": "'checkbox'",
- "defaultValue": "checkbox",
"widget": {
"component": "InputConfigurator"
}
@@ -2298,7 +2248,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2343,7 +2292,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2366,7 +2314,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2393,7 +2340,6 @@
{
"name": "value",
"type": "boolean",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中状态"
}
@@ -2508,6 +2454,7 @@
"description": {
"zh_CN": "复选框选项数据源"
},
+ "defaultValue": [],
"required": false,
"readOnly": false,
"disabled": false,
@@ -2536,7 +2483,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2563,7 +2509,6 @@
{
"name": "value",
"type": "any[]",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中的值数组"
}
@@ -2660,13 +2605,13 @@
"description": {
"zh_CN": "单选框类型"
},
+ "defaultValue": "radio",
"required": true,
"readOnly": true,
"disabled": true,
"cols": 12,
"labelPosition": "left",
"type": "'radio'",
- "defaultValue": "radio",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -2777,7 +2722,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2924,7 +2868,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -2951,7 +2894,6 @@
{
"name": "value",
"type": "any",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中的值"
}
@@ -3050,7 +2992,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -3073,7 +3014,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -3144,7 +3084,6 @@
{
"name": "value",
"type": "boolean",
- "defaultValue": "",
"description": {
"zh_CN": "当前开关状态"
}
@@ -3243,7 +3182,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "info",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -3306,7 +3244,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 3000,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -3431,7 +3368,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "top",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -3504,7 +3440,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "hover",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -3626,7 +3561,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "always",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -3663,7 +3597,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": true,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -3686,7 +3619,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -3836,7 +3768,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -3907,7 +3838,6 @@
{
"name": "response",
"type": "any",
- "defaultValue": "",
"description": {
"zh_CN": "服务器响应数据"
}
@@ -3915,7 +3845,6 @@
{
"name": "file",
"type": "File",
- "defaultValue": "",
"description": {
"zh_CN": "上传的文件对象"
}
@@ -3938,7 +3867,6 @@
{
"name": "error",
"type": "Error",
- "defaultValue": "",
"description": {
"zh_CN": "错误信息"
}
@@ -3946,7 +3874,6 @@
{
"name": "file",
"type": "File",
- "defaultValue": "",
"description": {
"zh_CN": "上传的文件对象"
}
@@ -4046,7 +3973,6 @@
"cols": 12,
"labelPosition": "left",
"type": "true | null",
- "defaultValue": null,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -4069,7 +3995,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "left",
"widget": {
"component": "SelectConfigurator",
"props": {
@@ -4106,7 +4031,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "100px",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -4218,7 +4142,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 24,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4241,7 +4164,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 0,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4529,7 +4451,6 @@
"cols": 12,
"labelPosition": "left",
"type": "string",
- "defaultValue": "yyyy-MM-dd",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -4552,7 +4473,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -4579,7 +4499,6 @@
{
"name": "value",
"type": "Date[]",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中的日期范围 [开始日期, 结束日期]"
}
@@ -4680,7 +4599,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 0,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4703,7 +4621,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 0,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4726,7 +4643,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 100,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4749,7 +4665,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 1,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4772,7 +4687,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -4799,7 +4713,6 @@
{
"name": "value",
"type": "number",
- "defaultValue": "",
"description": {
"zh_CN": "当前滑块的值"
}
@@ -4899,7 +4812,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 0,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4922,7 +4834,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 5,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -4945,7 +4856,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -4972,7 +4882,6 @@
{
"name": "value",
"type": "number",
- "defaultValue": "",
"description": {
"zh_CN": "当前评分的值"
}
@@ -5116,7 +5025,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -5139,7 +5047,6 @@
"cols": 12,
"labelPosition": "left",
"type": "boolean",
- "defaultValue": false,
"widget": {
"component": "CheckBoxConfigurator",
"props": {
@@ -5162,7 +5069,6 @@
"cols": 12,
"labelPosition": "left",
"type": "number",
- "defaultValue": 3,
"widget": {
"component": "NumberConfigurator",
"props": {
@@ -5211,7 +5117,6 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前输入值"
}
@@ -5234,7 +5139,6 @@
{
"name": "event",
"type": "FocusEvent",
- "defaultValue": "",
"description": {
"zh_CN": "焦点事件对象"
}
@@ -5257,7 +5161,6 @@
{
"name": "event",
"type": "FocusEvent",
- "defaultValue": "",
"description": {
"zh_CN": "焦点事件对象"
}
diff --git a/packages/materials/angular-opentiny-ng/src/meta/meta.ts b/packages/materials/angular-opentiny-ng/src/meta/meta.ts
new file mode 100644
index 00000000..ba63fd91
--- /dev/null
+++ b/packages/materials/angular-opentiny-ng/src/meta/meta.ts
@@ -0,0 +1,18 @@
+import type { IMaterialsMeta, IExample, IMaterialsProtocol } from '@opentiny/genui-sdk-core';
+import bundleJson from './materials/bundle.json' with { type: 'json' };
+import { examples as allExamples } from './example-schema';
+import { whiteList } from './white-list';
+
+const metaMaterials = [bundleJson] as IMaterialsProtocol[];
+
+function filterExamples(ids: string[]) {
+ return allExamples.filter((example): example is IExample => !!example.id && ids.includes(example.id));
+}
+
+export const materialsMeta: IMaterialsMeta = {
+ materials: metaMaterials,
+ wrapperComponent: 'TiCard',
+ whiteList,
+ examples: filterExamples(['form', 'info', 'grid', 'tabs', 'pagination']),
+ rules: [],
+};
diff --git a/packages/materials/angular-opentiny-ng/src/render-config/white-list.ts b/packages/materials/angular-opentiny-ng/src/meta/white-list.ts
similarity index 100%
rename from packages/materials/angular-opentiny-ng/src/render-config/white-list.ts
rename to packages/materials/angular-opentiny-ng/src/meta/white-list.ts
diff --git a/packages/materials/angular-opentiny-ng/src/render-config/example-schema.ts b/packages/materials/angular-opentiny-ng/src/render-config/example-schema.ts
deleted file mode 100644
index 1f82b3ab..00000000
--- a/packages/materials/angular-opentiny-ng/src/render-config/example-schema.ts
+++ /dev/null
@@ -1,1011 +0,0 @@
-export const formSchema = {
- 'state': {
- 'formData': {
- 'name': '张三',
- 'sex': '男',
- 'department': 'HR',
- 'protocolStart': '2023-01-01',
- 'email': '',
- },
- },
- 'methods': {
- 'departChange': {
- 'type': 'JSFunction',
- 'value': 'function departChange(value) { console.log(value) }',
- },
- 'handleSubmit': {
- 'type': 'JSFunction',
- 'value': 'function handleSubmit() { console.log(this.state.formData) }',
- },
- },
- 'componentName': 'Page',
- 'props': {
- 'style': 'width: 414px;',
- },
- 'children': [
- {
- 'componentName': 'h3',
- 'props': {},
- 'children': '更新员工信息',
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 16px;',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 8px;',
- },
- 'children': [
- {
- 'componentName': 'label',
- 'props': {
- 'style': 'font-weight: bold;',
- },
- 'children': '姓名',
- },
- {
- 'componentName': 'TiText',
- 'props': {
- 'placeholder': '请输入',
- 'ngModel': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.name',
- },
- },
- 'directives': [
- {
- 'directiveName': 'ngModel',
- },
- {
- 'directiveName': 'defaultValueAccessor',
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 8px;',
- },
- 'children': [
- {
- 'componentName': 'label',
- 'props': {
- 'style': 'font-weight: bold;',
- },
- 'children': '工号',
- },
- {
- 'componentName': 'TiText',
- 'props': {
- 'disabled': true,
- 'ngModel': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.id',
- },
- },
- 'directives': [
- {
- 'directiveName': 'ngModel',
- },
- {
- 'directiveName': 'defaultValueAccessor',
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 8px;',
- },
- 'children': [
- {
- 'componentName': 'label',
- 'props': {
- 'style': 'font-weight: bold;',
- },
- 'children': '性别',
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; gap: 16px;',
- },
- 'children': [
- {
- 'componentName': 'TiRadio',
- 'props': {
- 'value': '男',
- 'label': '男',
- },
- },
- {
- 'componentName': 'TiRadio',
- 'props': {
- 'value': '女',
- 'label': '女',
- },
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 8px;',
- },
- 'children': [
- {
- 'componentName': 'label',
- 'props': {
- 'style': 'font-weight: bold;',
- },
- 'children': '部门',
- },
- {
- 'componentName': 'TiSelect',
- 'props': {
- 'placeholder': '请选择',
- 'ngModel': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.department',
- },
- 'options': [
- {
- 'value': 'HR',
- 'label': '人事部',
- },
- {
- 'value': 'other',
- 'label': '其他部门',
- },
- ],
- 'ngModelChange': {
- 'type': 'JSExpression',
- 'value': 'this.departChange',
- },
- },
- 'directives': [
- {
- 'directiveName': 'ngModel',
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 8px;',
- },
- 'children': [
- {
- 'componentName': 'label',
- 'props': {
- 'style': 'font-weight: bold;',
- },
- 'children': '入职日期',
- },
- {
- 'componentName': 'TiDate',
- 'props': {
- 'placeholder': '请选择日期',
- 'disabled': true,
- 'ngModel': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.protocolStart',
- },
- 'format': 'yyyy-MM-dd',
- },
- 'directives': [
- {
- 'directiveName': 'ngModel',
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; gap: 8px; margin-top: 16px;',
- },
- 'children': [
- {
- 'componentName': 'TiButton',
- 'props': {
- 'type': 'primary',
- 'onClick': {
- 'type': 'JSExpression',
- 'value': 'this.handleSubmit',
- },
- },
- 'children': '确认',
- },
- {
- 'componentName': 'TiButton',
- 'props': {
- 'type': 'default',
- },
- 'children': '取消',
- },
- ],
- },
- ],
- },
- ],
-};
-
-export const infoCardSchema = {
- 'componentName': 'Page',
- 'children': [
- {
- 'componentName': 'h3',
- 'props': {
- 'style': 'font-size: 14px;font-weight: bold;line-height:2;margin-bottom:20px;display:block;',
- },
- 'children': '员工信息详情',
- },
- {
- 'componentName': 'TiCard',
- 'props': {
- 'header': '员工信息',
- 'style': 'width: 374px;',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex; flex-direction: column; gap: 16px; padding: 20px;',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex;',
- },
- 'children': [
- {
- 'componentName': 'span',
- 'props': {
- 'style': 'width: 80px; font-weight: bold;',
- },
- 'children': '姓名',
- },
- {
- 'componentName': 'span',
- 'children': '张三',
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex;',
- },
- 'children': [
- {
- 'componentName': 'span',
- 'props': {
- 'style': 'width: 80px; font-weight: bold;',
- },
- 'children': '电话',
- },
- {
- 'componentName': 'span',
- 'children': '18856254558',
- },
- ],
- },
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'display: flex;',
- },
- 'children': [
- {
- 'componentName': 'span',
- 'props': {
- 'style': 'width: 80px; font-weight: bold;',
- },
- 'children': '部门',
- },
- {
- 'componentName': 'span',
- 'children': 'HR',
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- 'id': 'body',
-};
-
-export const gridSchema = {
- 'componentName': 'Page',
- 'css':
- '.page-base-style {padding: 24px;background: #FFFFFF;}.block-base-style {margin: 16px;}.component-base-style {margin: 8px;}',
- 'props': { 'className': 'page-base-style' },
- 'lifeCycles': {},
- 'children': [
- {
- 'componentName': 'TiTable',
- 'props': {
- 'srcData': {
- 'type': 'JSExpression',
- 'value': 'this.state.srcData',
- },
- 'displayedData': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.displayedData',
- },
- 'columns': {
- 'type': 'JSExpression',
- 'value': 'this.state.columns',
- },
- 'className': 'component-base-style',
- },
- 'children': [
- {
- 'componentName': 'table',
- 'children': [
- {
- 'componentName': 'thead',
- 'children': [
- {
- 'componentName': 'tr',
- 'children': [
- {
- 'componentName': 'th',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'column.title',
- },
- },
- },
- ],
- 'loop': {
- 'type': 'JSExpression',
- 'value': 'this.state.columns',
- },
- 'loopArgs': ['column'],
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'tbody',
- 'children': [
- {
- 'componentName': 'tr',
- 'loop': {
- 'type': 'JSExpression',
- 'value': 'this.state.displayedData',
- },
- 'loopArgs': ['row'],
- 'children': [
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.name',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.id',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.sex',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.department',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.protocolStart',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.email',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'TinyButton',
- 'props': {
- 'onClick': {
- 'type': 'JSFunction',
- 'value': 'function() { this.deleteRow(row) }',
- },
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': '`删除${row.name}`',
- },
- },
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- 'state': {
- 'columns': [
- { 'field': 'name', 'title': '姓名' },
- { 'field': 'id', 'title': '工号' },
- { 'field': 'sex', 'title': '性别' },
- { 'field': 'department', 'title': '部门' },
- { 'field': 'protocolStart', 'title': '入职日期' },
- { 'field': 'email', 'title': '邮箱' },
- { 'field': 'actions', 'title': '操作' },
- ],
- 'srcData': [
- {
- 'name': '李四',
- 'id': '2',
- 'sex': '女',
- 'department': '技术部',
- 'protocolStart': '2019-05-15',
- 'email': 'lisi@test.com',
- },
- {
- 'name': '王五',
- 'id': '3',
- 'sex': '男',
- 'department': '市场部',
- 'protocolStart': '2020-03-20',
- 'email': 'wangwu@test.com',
- },
- ],
- 'displayedData': [],
- },
- 'methods': {
- 'deleteRow': {
- 'type': 'JSFunction',
- 'value': 'function(row) { this.state.srcData = this.state.srcData.filter(item => item.id !== row.id) }',
- },
- },
- 'dataSource': { 'list': [] },
- 'id': 'body',
-};
-
-export const tabsSchema = {
- 'componentName': 'Page',
- 'fileName': 'Untitled',
- 'css':
- '.page-base-style {\n padding: 24px;background: #FFFFFF;\n}\n\n.block-base-style {\n margin: 16px;\n}\n\n.component-base-style {\n margin: 8px;\n}\n',
- 'props': {
- 'className': 'page-base-style',
- },
- 'lifeCycles': {},
- 'children': [
- {
- 'componentName': 'div',
- 'id': 'e9a7b6c5',
- 'props': {
- 'style': 'display: flex; flex-direction: column; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'h2',
- 'id': 'f2g3h4i5',
- 'props': {
- 'style': 'font-size: 24px; font-weight: bold; margin-bottom: 20px;',
- },
- 'children': '降本增效,加速企业数字化转型',
- },
- {
- 'componentName': 'TiTabs',
- 'id': 'j6k7l8m9',
- 'props': {
- 'className': 'component-base-style',
- },
- 'children': [
- {
- 'componentName': 'TiTab',
- 'id': 'n0o1p2q3',
- 'props': {
- 'header': '精选推荐',
- 'id': 'tab1',
- 'active': true,
- },
- 'children': [
- {
- 'componentName': 'div',
- 'id': 'r4s5t6u7',
- 'props': {
- 'style': 'display: flex; flex-wrap: wrap; justify-content: space-around; gap: 20px; padding: 20px;',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'id': 'v8w9x0y1',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'z2a3b4c5',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/Domains.png',
- 'alt': '域名注册服务',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'h4',
- 'id': 'd6e7f8g9',
- 'props': {
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- 'children': '域名注册服务',
- },
- {
- 'componentName': 'p',
- 'id': 'h0i1j2k3',
- 'props': {
- 'style': 'font-size: 14px; color: #666;',
- },
- 'children': '适用于网站建设、域名投资等场景',
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'l4m5n6o7',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'p8q9r0s1',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/mail0918.png',
- 'alt': '华为云企业邮箱',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'h4',
- 'id': 't2u3v4w5',
- 'props': {
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- 'children': '华为云企业邮箱',
- },
- {
- 'componentName': 'p',
- 'id': 'x6y7z8a9',
- 'props': {
- 'style': 'font-size: 14px; color: #666;',
- },
- 'children': '免费试用,无限容量,全球畅邮',
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'b0c1d2e3',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'f4g5h6i7',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/Cloudsite.png',
- 'alt': '企业门户(原云速建站)',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'h4',
- 'id': 'j8k9l0m1',
- 'props': {
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- 'children': '企业门户(原云速建站)',
- },
- {
- 'componentName': 'p',
- 'id': 'n2o3p4q5',
- 'props': {
- 'style': 'font-size: 14px; color: #666;',
- },
- 'children': '无需代码,一键拖拽,3000+模板随心选',
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'r6s7t8u9',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'v0w1x2y3',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/china/zh-cn/yunying/new-home/markplace/home_icon_14.svg',
- 'alt': '财税卫士',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'h4',
- 'id': 'z4a5b6c7',
- 'props': {
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- 'children': '财税卫士',
- },
- {
- 'componentName': 'p',
- 'id': 'd8e9f0g1',
- 'props': {
- 'style': 'font-size: 14px; color: #666;',
- },
- 'children': '智能财税风控检测软件,助力企业合规',
- },
- ],
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'TiTab',
- 'id': 'h2i3j4k5',
- 'props': {
- 'header': '企业初创',
- 'id': 'tab2',
- },
- 'children': [],
- },
- {
- 'componentName': 'TiTab',
- 'id': 'l6m7n8o9',
- 'props': {
- 'header': '企业营销',
- 'id': 'tab3',
- },
- 'children': [],
- },
- {
- 'componentName': 'TiTab',
- 'id': 'p0q1r2s3',
- 'props': {
- 'header': '企业办公',
- 'id': 'tab4',
- },
- 'children': [],
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 't4u5v6w7',
- 'props': {
- 'style': 'text-align: center; margin-top: 20px;',
- },
- 'children': [
- {
- 'componentName': 'a',
- 'id': 'x8y9z0a1',
- 'props': {
- 'style': 'font-size: 16px; color: #1890ff; text-decoration: none;',
- 'href': '#',
- },
- 'children': '查看企业应用中心 >',
- },
- ],
- },
- ],
- },
- ],
- 'dataSource': {
- 'list': [],
- },
- 'methods': {},
- 'bridge': {
- 'imports': [],
- },
- 'state': {},
- 'inputs': [],
- 'outputs': [],
- 'id': 'body',
-};
-
-export const paginationSchema = {
- 'componentName': 'Page',
- 'props': {
- 'className': 'page-base-style',
- },
- 'css': '.page-base-style {padding: 24px;background: #FFFFFF;}',
- 'children': [
- {
- 'componentName': 'TiTable',
- 'props': {
- 'srcData': {
- 'type': 'JSExpression',
- 'value': 'this.state.srcData',
- },
- 'displayedData': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.displayedData',
- },
- 'columns': {
- 'type': 'JSExpression',
- 'value': 'this.state.columns',
- },
- },
- 'children': [
- {
- 'componentName': 'table',
- 'children': [
- {
- 'componentName': 'thead',
- 'children': [
- {
- 'componentName': 'tr',
- 'children': [
- {
- 'componentName': 'th',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'column.title',
- },
- },
- },
- ],
- 'loop': {
- 'type': 'JSExpression',
- 'value': 'this.state.columns',
- },
- 'loopArgs': ['column'],
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'tbody',
- 'children': [
- {
- 'componentName': 'tr',
- 'children': [
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.id',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.name',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.department',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'td',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'text': {
- 'type': 'JSExpression',
- 'value': 'row.email',
- },
- },
- },
- ],
- },
- ],
- 'loop': {
- 'type': 'JSExpression',
- 'value': 'this.state.displayedData',
- },
- 'loopArgs': ['row'],
- },
- ],
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'TiPagination',
- 'props': {
- 'currentPage': {
- 'type': 'JSExpression',
- 'value': 'this.state.currentPage',
- },
- 'pageSize': {
- 'type': 'JSExpression',
- 'value': 'this.state.pageSize',
- },
- 'total': {
- 'type': 'JSExpression',
- 'value': 'this.state.total',
- },
- 'currentPageChange': {
- 'type': 'JSFunction',
- 'value': 'function(page) { this.state.currentPage = page }',
- },
- 'pageSizeChange': {
- 'type': 'JSFunction',
- 'value': 'function(size) { this.state.pageSize = size }',
- },
- },
- },
- ],
- 'state': {
- 'currentPage': 1,
- 'pageSize': 10,
- 'total': 100,
- 'columns': [
- { 'field': 'id', 'title': 'ID' },
- { 'field': 'name', 'title': '姓名' },
- { 'field': 'department', 'title': '部门' },
- { 'field': 'email', 'title': '邮箱' },
- ],
- 'srcData': {
- 'data': [
- { 'id': '1', 'name': '张三', 'department': 'HR', 'email': 'zhangsan@test.com' },
- { 'id': '2', 'name': '李四', 'department': '技术部', 'email': 'lisi@test.com' },
- { 'id': '3', 'name': '王五', 'department': '市场部', 'email': 'wangwu@test.com' },
- ],
- },
- 'displayedData': [],
- },
- 'id': 'body',
-};
-
-export const examples = [
- { name: '双向绑定的表单', schema: formSchema },
- { name: '信息展示卡片', schema: infoCardSchema },
- { name: '表格卡片', schema: gridSchema },
- { name: 'Tabs卡片', schema: tabsSchema },
- { name: '分页表格', schema: paginationSchema },
-];
diff --git a/packages/materials/angular-opentiny-ng/src/render-config/index.ts b/packages/materials/angular-opentiny-ng/src/render-config/index.ts
deleted file mode 100644
index 38f29768..00000000
--- a/packages/materials/angular-opentiny-ng/src/render-config/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './merge';
diff --git a/packages/materials/angular-opentiny-ng/src/render-config/merge.ts b/packages/materials/angular-opentiny-ng/src/render-config/merge.ts
deleted file mode 100644
index 2510a7ca..00000000
--- a/packages/materials/angular-opentiny-ng/src/render-config/merge.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import bundleJson from './bundle.json' with { type: 'json' };
-import { examples } from './example-schema';
-import { whiteList } from './white-list';
-
-// 定义渲染器配置的类型
-interface IRendererConfig {
- materialsList: any[];
- examples: any[];
- whiteList: string[];
- wrapperComponent: string;
-}
-
-export const ngRendererConfig: IRendererConfig = {
- materialsList: [bundleJson],
- examples,
- whiteList,
- wrapperComponent: 'TiCard',
-};
diff --git a/packages/materials/angular-opentiny-ng/vite.config.ts b/packages/materials/angular-opentiny-ng/vite.config.ts
index 246fd8f7..d13a0649 100644
--- a/packages/materials/angular-opentiny-ng/vite.config.ts
+++ b/packages/materials/angular-opentiny-ng/vite.config.ts
@@ -14,11 +14,13 @@ export default defineConfig({
lib: {
entry: {
index: path.resolve(__dirname, './src/index.ts'),
- 'render-config': path.resolve(__dirname, './src/render-config/index.ts'),
+ meta: path.resolve(__dirname, './src/meta/index.ts'),
+ materials: path.resolve(__dirname, './src/materials/index.ts'),
},
formats: ['es'],
fileName: (format, entryName) => `${entryName}.js`,
},
+ sourcemap: true,
rollupOptions: {
external: [...Object.keys(packageJson.dependencies || {}).map(name => new RegExp(`^${escapeStringRegexp(name)}(/|$)`))],
},
diff --git a/packages/materials/vue-element-plus/CONTRIBUTING.md b/packages/materials/vue-element-plus/CONTRIBUTING.md
new file mode 100644
index 00000000..4991bd58
--- /dev/null
+++ b/packages/materials/vue-element-plus/CONTRIBUTING.md
@@ -0,0 +1,74 @@
+# Contributing
+
+Local development and extension notes for this materials package. End users should start with [README.md](./README.md).
+
+## Package Structure
+
+```text
+vue-element-plus/
+├── src/
+│ ├── index.ts # Unified entry
+│ ├── materials/
+│ │ ├── index.ts # Export materials
+│ │ ├── materials.ts # Materials registry
+│ │ └── components/
+│ │ ├── index.ts
+│ │ └── components.ts # Element Plus component mapping
+│ └── meta/
+│ ├── index.ts # Export materialsMeta
+│ ├── meta.ts # Materials metadata
+│ ├── white-list.ts # LLM componentName whitelist
+│ ├── example-schema.ts # Prompt example schemas
+│ ├── examples/ # Example JSON
+│ └── materials/
+│ └── bundle.json # Element Plus base materials
+├── test/
+│ ├── mock/ # JSON demos (form-binding, table, info-card, tabs)
+│ ├── App.vue # Local tab-switched rendering
+│ └── schema-context.ts # Schema helpers for demos
+├── vite.config.ts # Package build config
+├── vite.config.test.ts # Local demo dev config
+└── __tests__/
+ └── schema-demos.test.ts # Automated tests based on mock JSON
+```
+
+## Build & Verify
+
+```bash
+# Build
+pnpm -F @opentiny/genui-sdk-materials-vue-element-plus build
+
+# Local JSON demos (test/mock/, tab-switched rendering)
+pnpm -F @opentiny/genui-sdk-materials-vue-element-plus dev
+
+# Automated tests
+pnpm -F @opentiny/genui-sdk-materials-vue-element-plus test
+```
+
+To add a demo: put a JSON file under `test/mock/` and register it in `test/mock/index.ts`.
+
+## Dev Path Aliases (Optional)
+
+Add to `tsconfig`:
+
+```json
+{
+ "paths": {
+ "@opentiny/genui-sdk-materials-vue-element-plus": [
+ "../../../packages/materials/vue-element-plus/src/index.ts"
+ ],
+ "@opentiny/genui-sdk-materials-vue-element-plus/materials": [
+ "../../../packages/materials/vue-element-plus/src/materials/index.ts"
+ ],
+ "@opentiny/genui-sdk-materials-vue-element-plus/meta": [
+ "../../../packages/materials/vue-element-plus/src/meta/index.ts"
+ ]
+ }
+}
+```
+
+## Extending Components
+
+1. Add the component schema description in `meta/materials/bundle.json`
+2. Add the `componentName` in `meta/white-list.ts`
+3. Register the corresponding `element-plus` export in `materials/components/components.ts`
diff --git a/packages/materials/vue-element-plus/README.md b/packages/materials/vue-element-plus/README.md
new file mode 100644
index 00000000..e49d57ec
--- /dev/null
+++ b/packages/materials/vue-element-plus/README.md
@@ -0,0 +1,69 @@
+# @opentiny/genui-sdk-materials-vue-element-plus
+
+
+A GenUI Vue materials package based on [Element Plus](https://element-plus.org/), for schema-driven page generation and rendering.
+
+## Install
+
+```bash
+npm install @opentiny/genui-sdk-materials-vue-element-plus element-plus vue
+```
+
+Peer dependencies `vue` and `element-plus` must also be installed.
+
+## Quick Start
+
+### Frontend Rendering
+
+Import Element Plus styles at the app entry, and inject materials via `ConfigProvider`:
+
+```ts
+import 'element-plus/dist/index.css';
+import { GenuiConfigProvider, GenuiChat } from '@opentiny/genui-sdk-vue';
+import { materials } from '@opentiny/genui-sdk-materials-vue-element-plus/materials';
+```
+
+```vue
+
+
+
+```
+
+### Generate LLM Prompt (Server)
+
+```ts
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-element-plus/meta';
+
+const systemPrompt = genPrompt('Vue', materialsMeta, customConfig);
+```
+
+`materialsMeta.wrapperComponent` defaults to `ElCard`.
+
+## API
+
+| Export Path | Exports | Description |
+|-------------|---------|-------------|
+| `@opentiny/genui-sdk-materials-vue-element-plus` | `materials`, `materialsMeta` | Unified entry |
+| `.../materials` | `materials` | Inject into `ConfigProvider` for schema rendering |
+| `.../meta` | `materialsMeta` | For `genPrompt()` / building the server system prompt |
+
+### `materials`
+
+Component registry mapping Element Plus components, used by the renderer to resolve nodes by `componentName`.
+
+### `materialsMeta`
+
+Materials metadata, including:
+
+- `materials`: Protocol descriptions for components / blocks / snippets
+- `wrapperComponent`: Default wrapper component (`ElCard`)
+- `whiteList`: Whitelist of `componentName` values available to the LLM
+- `examples`: Prompt example schemas (form / info / table)
+- `rules`: Extra constraint rules
+
+Component library: `element-plus`.
+
+## More
+
+For package development, local demos, and extending components, see [CONTRIBUTING.md](./CONTRIBUTING.md).
diff --git a/packages/materials/vue-element-plus/__tests__/schema-demos.test.ts b/packages/materials/vue-element-plus/__tests__/schema-demos.test.ts
new file mode 100644
index 00000000..d363b620
--- /dev/null
+++ b/packages/materials/vue-element-plus/__tests__/schema-demos.test.ts
@@ -0,0 +1,96 @@
+import { describe, it, expect } from 'vitest';
+import { createContext, parseSchemaValue, runLifeCycle } from '../test/schema-context';
+import { demos } from '../test/mock';
+
+function findComponent(schema: unknown, componentName: string): Record | null {
+ if (!schema || typeof schema !== 'object') {
+ return null;
+ }
+
+ const node = schema as Record;
+ if (node.componentName === componentName) {
+ return node;
+ }
+
+ const children = node.children;
+ if (Array.isArray(children)) {
+ for (const child of children) {
+ const found = findComponent(child, componentName);
+ if (found) {
+ return found;
+ }
+ }
+ }
+
+ return null;
+}
+
+describe('schema demos', () => {
+ demos.forEach(({ id, label, schema }) => {
+ it(`${label} (${id}) has Page root`, () => {
+ expect(schema.componentName).toBe('Page');
+ });
+ });
+
+ it('form-binding demo submit updates submitResult', () => {
+ const schema = demos.find((demo) => demo.id === 'form-binding')!.schema;
+ const ctx = createContext(schema);
+ const onClick = parseSchemaValue(
+ { type: 'JSFunction', value: 'function() { this.handleSubmit(); }' },
+ {},
+ ctx,
+ ) as () => void;
+
+ onClick();
+ expect((ctx.state as { submitResult: string }).submitResult).toContain('已提交:');
+ expect((ctx.state as { formData: { name: string } }).formData.name).toBe('张三');
+ });
+
+ it('form-binding demo reset clears form state', () => {
+ const schema = demos.find((demo) => demo.id === 'form-binding')!.schema;
+ const ctx = createContext(schema);
+ (ctx.state as { formData: { name: string } }).formData.name = '测试';
+ (ctx.state as { submitResult: string }).submitResult = '已有结果';
+
+ (ctx.handleReset as () => void)();
+ expect((ctx.state as { formData: { name: string } }).formData.name).toBe('');
+ expect((ctx.state as { submitResult: string }).submitResult).toBe('');
+ });
+
+ it('table demo onMounted loads tableData', () => {
+ const schema = demos.find((demo) => demo.id === 'table')!.schema;
+ const ctx = createContext(schema);
+
+ expect((ctx.state as { tableData: unknown[] }).tableData).toEqual([]);
+ runLifeCycle(ctx, 'onMounted');
+ expect((ctx.state as { tableData: unknown[] }).tableData).toHaveLength(4);
+ });
+
+ it('table demo has no action column', () => {
+ const schema = demos.find((demo) => demo.id === 'table')!.schema;
+ const table = findComponent(schema, 'ElTable');
+ const columns = (table?.children as Array<{ props?: { label?: string } }>) ?? [];
+
+ expect(columns.some((column) => column.props?.label === '操作')).toBe(false);
+ });
+
+ it('table status tag resolves row expression', () => {
+ const schema = demos.find((demo) => demo.id === 'table')!.schema;
+ const ctx = createContext(schema);
+ const tagType = parseSchemaValue(
+ { type: 'JSExpression', value: "row.status === '在职' ? 'success' : 'info'" },
+ { row: { status: '在职' } },
+ ctx,
+ );
+
+ expect(tagType).toBe('success');
+ });
+
+ it('tabs demo handleTabChange updates activeTab', () => {
+ const schema = demos.find((demo) => demo.id === 'tabs')!.schema;
+ const ctx = createContext(schema);
+
+ (ctx.handleTabChange as (key: string) => void)('detail');
+ expect((ctx.state as { activeTab: string }).activeTab).toBe('detail');
+ });
+});
diff --git a/packages/materials/vue-element-plus/package.json b/packages/materials/vue-element-plus/package.json
new file mode 100644
index 00000000..955dd7c7
--- /dev/null
+++ b/packages/materials/vue-element-plus/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "@opentiny/genui-sdk-materials-vue-element-plus",
+ "version": "1.0.0",
+ "description": "GenUI Vue materials package based on Element Plus",
+ "author": "OpenTiny Team",
+ "license": "MIT",
+ "homepage": "https://opentiny.design/genui-sdk",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/opentiny/genui-sdk"
+ },
+ "bugs": {
+ "url": "https://github.com/opentiny/genui-sdk/issues"
+ },
+ "keywords": [
+ "vue",
+ "element-plus",
+ "component",
+ "library",
+ "llm",
+ "generative-ui",
+ "stream-ui"
+ ],
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "type": "module",
+ "files": [
+ "dist",
+ "README.md",
+ "CONTRIBUTING.md"
+ ],
+ "scripts": {
+ "build": "vite build",
+ "dev": "vite --config vite.config.test.ts",
+ "test": "vitest run",
+ "test:watch": "vitest"
+ },
+ "dependencies": {
+ "@opentiny/genui-sdk-core": "workspace:*"
+ },
+ "peerDependencies": {
+ "element-plus": "^2.9.0",
+ "vue": "^3.5.13"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.0.0",
+ "@vue/tsconfig": "^0.8.1",
+ "element-plus": "^2.9.0",
+ "escape-string-regexp": "^1.0.5",
+ "typescript": "^5.8.2",
+ "vite": "^6.0.0",
+ "vite-plugin-css-injected-by-js": "^3.5.2",
+ "vite-plugin-dts": "^4.0.0",
+ "vitest": "^3.0.0",
+ "vue": "^3.5.13"
+ },
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js",
+ "require": "./dist/index.js"
+ },
+ "./meta": {
+ "types": "./dist/meta.d.ts",
+ "import": "./dist/meta.js",
+ "require": "./dist/meta.js"
+ },
+ "./materials": {
+ "types": "./dist/materials.d.ts",
+ "import": "./dist/materials.js",
+ "require": "./dist/materials.js"
+ }
+ }
+}
diff --git a/packages/materials/vue-element-plus/src/index.ts b/packages/materials/vue-element-plus/src/index.ts
new file mode 100644
index 00000000..47ef1e6c
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/index.ts
@@ -0,0 +1,2 @@
+export * from './meta';
+export * from './materials';
diff --git a/packages/materials/vue-element-plus/src/materials/components/components.ts b/packages/materials/vue-element-plus/src/materials/components/components.ts
new file mode 100644
index 00000000..3ee5241d
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/materials/components/components.ts
@@ -0,0 +1,50 @@
+import type { Component } from 'vue';
+import {
+ ElInput,
+ ElDatePicker,
+ ElButton,
+ ElForm,
+ ElFormItem,
+ ElTable,
+ ElTableColumn,
+ ElCard,
+ ElRow,
+ ElCol,
+ ElSelect,
+ ElOption,
+ ElRadio,
+ ElRadioGroup,
+ ElSwitch,
+ ElCheckbox,
+ ElTag,
+ ElDivider,
+ ElTabs,
+ ElTabPane,
+} from 'element-plus';
+
+export interface IComponents {
+ [key: string]: Component;
+}
+
+export const components: IComponents = {
+ ElInput,
+ ElDatePicker,
+ ElButton,
+ ElForm,
+ ElFormItem,
+ ElTable,
+ ElTableColumn,
+ ElCard,
+ ElRow,
+ ElCol,
+ ElSelect,
+ ElOption,
+ ElRadio,
+ ElRadioGroup,
+ ElSwitch,
+ ElCheckbox,
+ ElTag,
+ ElDivider,
+ ElTabs,
+ ElTabPane,
+};
diff --git a/packages/materials/vue-element-plus/src/materials/components/index.ts b/packages/materials/vue-element-plus/src/materials/components/index.ts
new file mode 100644
index 00000000..07635cbb
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/materials/components/index.ts
@@ -0,0 +1 @@
+export * from './components';
diff --git a/packages/materials/vue-element-plus/src/materials/index.ts b/packages/materials/vue-element-plus/src/materials/index.ts
new file mode 100644
index 00000000..ea409aff
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/materials/index.ts
@@ -0,0 +1 @@
+export * from './materials';
diff --git a/packages/materials/vue-element-plus/src/materials/materials.ts b/packages/materials/vue-element-plus/src/materials/materials.ts
new file mode 100644
index 00000000..9a2cfc47
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/materials/materials.ts
@@ -0,0 +1,11 @@
+import { buildMaterialDefaultValueMap, type IMaterials } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '../meta';
+import { components } from './components';
+
+const standardRequiredCompleteFieldSelectors = ['[componentName=ElCard] > props > shadow'];
+
+export const materials: IMaterials = {
+ components,
+ requiredCompleteFieldSelectors: standardRequiredCompleteFieldSelectors,
+ defaultPropsMap: buildMaterialDefaultValueMap(materialsMeta),
+};
diff --git a/packages/materials/vue-element-plus/src/meta/example-schema.ts b/packages/materials/vue-element-plus/src/meta/example-schema.ts
new file mode 100644
index 00000000..50ce0eef
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/example-schema.ts
@@ -0,0 +1,10 @@
+import type { IExample } from '@opentiny/genui-sdk-core';
+import formSchema from './examples/form.json' with { type: 'json' };
+import infoCardSchema from './examples/info.json' with { type: 'json' };
+import tableSchema from './examples/table.json' with { type: 'json' };
+
+export const examples = [
+ { id: 'form', name: '双向绑定的表单', schema: formSchema },
+ { id: 'info', name: '信息展示卡片', schema: infoCardSchema },
+ { id: 'table', name: '数据表格', schema: tableSchema },
+] as IExample[];
diff --git a/packages/materials/vue-element-plus/src/meta/examples/form.json b/packages/materials/vue-element-plus/src/meta/examples/form.json
new file mode 100644
index 00000000..4277af53
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/examples/form.json
@@ -0,0 +1,163 @@
+{
+ "state": {
+ "formData": {
+ "name": "张三",
+ "sex": "男",
+ "department": "HR",
+ "protocolStart": "2023-01-01",
+ "email": ""
+ }
+ },
+ "componentName": "Page",
+ "props": {
+ "style": "width: 414px;"
+ },
+ "children": [
+ {
+ "componentName": "h3",
+ "props": {},
+ "children": "更新员工信息"
+ },
+ {
+ "componentName": "ElForm",
+ "props": {
+ "model": {
+ "type": "JSExpression",
+ "value": "this.state.formData"
+ },
+ "labelPosition": "top"
+ },
+ "children": [
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "姓名",
+ "prop": "name",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "ElInput",
+ "props": {
+ "placeholder": "请输入",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.name"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "性别",
+ "prop": "sex"
+ },
+ "children": [
+ {
+ "componentName": "ElRadioGroup",
+ "props": {
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.sex"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElRadio",
+ "props": {
+ "value": "男"
+ },
+ "children": "男"
+ },
+ {
+ "componentName": "ElRadio",
+ "props": {
+ "value": "女"
+ },
+ "children": "女"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "部门",
+ "prop": "department",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "ElSelect",
+ "props": {
+ "placeholder": "请选择",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.department"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElOption",
+ "props": {
+ "label": "人事部",
+ "value": "HR"
+ }
+ },
+ {
+ "componentName": "ElOption",
+ "props": {
+ "label": "其他部门",
+ "value": "other"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "入职日期",
+ "prop": "protocolStart"
+ },
+ "children": [
+ {
+ "componentName": "ElDatePicker",
+ "props": {
+ "type": "date",
+ "placeholder": "请选择日期",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.protocolStart"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": ""
+ },
+ "children": [
+ {
+ "componentName": "ElButton",
+ "props": {
+ "type": "primary"
+ },
+ "children": "确认"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/src/meta/examples/info.json b/packages/materials/vue-element-plus/src/meta/examples/info.json
new file mode 100644
index 00000000..1812d706
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/examples/info.json
@@ -0,0 +1,57 @@
+{
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "style": "font-size: 14px;font-weight: bold;line-height:2;margin-bottom:20px;display:block;",
+ "text": "员工信息详情"
+ }
+ },
+ {
+ "componentName": "ElCard",
+ "props": {
+ "header": "基本信息",
+ "shadow": "never"
+ },
+ "children": [
+ {
+ "componentName": "ElRow",
+ "props": { "gutter": 12 },
+ "children": [
+ {
+ "componentName": "ElCol",
+ "props": { "span": 6 },
+ "children": [{ "componentName": "Text", "props": { "text": "姓名" } }]
+ },
+ {
+ "componentName": "ElCol",
+ "props": { "span": 18 },
+ "children": [{ "componentName": "Text", "props": { "text": "张三" } }]
+ }
+ ]
+ },
+ {
+ "componentName": "ElDivider",
+ "props": {}
+ },
+ {
+ "componentName": "ElRow",
+ "props": { "gutter": 12 },
+ "children": [
+ {
+ "componentName": "ElCol",
+ "props": { "span": 6 },
+ "children": [{ "componentName": "Text", "props": { "text": "电话" } }]
+ },
+ {
+ "componentName": "ElCol",
+ "props": { "span": 18 },
+ "children": [{ "componentName": "Text", "props": { "text": "18856254558" } }]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/src/meta/examples/table.json b/packages/materials/vue-element-plus/src/meta/examples/table.json
new file mode 100644
index 00000000..c6beac6f
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/examples/table.json
@@ -0,0 +1,30 @@
+{
+ "componentName": "Page",
+ "props": {
+ "style": "padding: 16px;"
+ },
+ "children": [
+ {
+ "componentName": "h3",
+ "children": "员工列表"
+ },
+ {
+ "componentName": "ElTable",
+ "props": {
+ "data": [
+ { "name": "张三", "id": "10001", "sex": "男", "department": "HR", "protocolStart": "2023-01-01" },
+ { "name": "李四", "id": "10002", "sex": "女", "department": "研发", "protocolStart": "2022-06-15" }
+ ],
+ "stripe": true,
+ "style": "width: 100%;"
+ },
+ "children": [
+ { "componentName": "ElTableColumn", "props": { "prop": "name", "label": "姓名", "width": 120 } },
+ { "componentName": "ElTableColumn", "props": { "prop": "id", "label": "工号", "width": 100 } },
+ { "componentName": "ElTableColumn", "props": { "prop": "sex", "label": "性别", "width": 80 } },
+ { "componentName": "ElTableColumn", "props": { "prop": "department", "label": "部门" } },
+ { "componentName": "ElTableColumn", "props": { "prop": "protocolStart", "label": "入职日期", "width": 140 } }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/src/meta/index.ts b/packages/materials/vue-element-plus/src/meta/index.ts
new file mode 100644
index 00000000..c9942f46
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/index.ts
@@ -0,0 +1 @@
+export * from './meta';
diff --git a/packages/materials/vue-element-plus/src/meta/materials/bundle.json b/packages/materials/vue-element-plus/src/meta/materials/bundle.json
new file mode 100644
index 00000000..153a10e3
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/materials/bundle.json
@@ -0,0 +1,4161 @@
+{
+ "data": {
+ "framework": "Vue",
+ "materials": {
+ "components": [
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "输入框"
+ },
+ "component": "ElInput",
+ "icon": "input",
+ "description": "通过鼠标或键盘输入字符",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElInput",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "type",
+ "size"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ },
+ "description": {
+ "zh_CN": "绑定值"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "尺寸"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "default",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "large",
+ "value": "large"
+ },
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "type",
+ "label": {
+ "text": {
+ "zh_CN": "类型"
+ }
+ },
+ "description": {
+ "zh_CN": "类型"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "placeholder",
+ "label": {
+ "text": {
+ "zh_CN": "占位文本"
+ }
+ },
+ "description": {
+ "zh_CN": "输入框占位文本"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "I18nConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "maxlength",
+ "label": {
+ "text": {
+ "zh_CN": "最大长度"
+ }
+ },
+ "description": {
+ "zh_CN": "最大输入长度"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "disabled",
+ "label": {
+ "text": {
+ "zh_CN": "是否禁用"
+ }
+ },
+ "description": {
+ "zh_CN": "是否禁用"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "双向绑定值改变时触发"
+ },
+ "description": {
+ "zh_CN": "双向绑定值改变时触发"
+ }
+ },
+ "onBlur": {
+ "label": {
+ "zh_CN": "输入框失去焦点时触发"
+ },
+ "description": {
+ "zh_CN": "输入框失去焦点时触发"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "event",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "原生 event"
+ }
+ }
+ ],
+ "returns": {}
+ },
+ "defaultValue": ""
+ }
+ },
+ "slots": {
+ "prefix": {
+ "label": {
+ "zh_CN": "头部内容"
+ },
+ "description": {
+ "zh_CN": "输入框头部内容,只对非 type='textarea' 有效"
+ }
+ },
+ "suffix": {
+ "label": {
+ "zh_CN": "尾部内容"
+ },
+ "description": {
+ "zh_CN": "输入框尾部内容,只对非 type='textarea' 有效"
+ }
+ },
+ "prepend": {
+ "label": {
+ "zh_CN": "前置内容"
+ },
+ "description": {
+ "zh_CN": "输入框前置内容,只对非 type='textarea' 有效"
+ }
+ },
+ "append": {
+ "label": {
+ "zh_CN": "后置内容"
+ },
+ "description": {
+ "zh_CN": "输入框后置内容,只对非 type='textarea' 有效"
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "日期选择器"
+ },
+ "component": "ElDatePicker",
+ "icon": "datepick",
+ "description": "用于选择日期或时间,支持 date、datetime、daterange 等多种类型。",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElDatePicker",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "type",
+ "size"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ },
+ "description": {
+ "zh_CN": "绑定值"
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "readonly",
+ "label": {
+ "text": {
+ "zh_CN": "只读"
+ }
+ },
+ "description": {
+ "zh_CN": "是否只读"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "defaultValue": false,
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "disabled",
+ "label": {
+ "text": {
+ "zh_CN": "禁用"
+ }
+ },
+ "description": {
+ "zh_CN": "是否禁用"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "defaultValue": false,
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "输入框尺寸"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "allowClear": true,
+ "options": [
+ {
+ "label": "large",
+ "value": "large"
+ },
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "editable",
+ "label": {
+ "text": {
+ "zh_CN": "是否可编辑"
+ }
+ },
+ "description": {
+ "zh_CN": "文本框是否可编辑"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "defaultValue": true,
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "clearable",
+ "label": {
+ "text": {
+ "zh_CN": "是否可清除"
+ }
+ },
+ "description": {
+ "zh_CN": "是否显示清楚按钮"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "defaultValue": true,
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "placeholder",
+ "label": {
+ "text": {
+ "zh_CN": "占位文本"
+ }
+ },
+ "description": {
+ "zh_CN": "非范围选择时的占位内容"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": "",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "start-placeholder",
+ "label": {
+ "text": {
+ "zh_CN": "起始占位文本"
+ }
+ },
+ "description": {
+ "zh_CN": "范围选择时开始日期的占位内容"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": "",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "end-placeholder",
+ "label": {
+ "text": {
+ "zh_CN": "结束占位文本"
+ }
+ },
+ "description": {
+ "zh_CN": "范围选择时结束日期的占位内容"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": "",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "type",
+ "label": {
+ "text": {
+ "zh_CN": "类型"
+ }
+ },
+ "description": {
+ "zh_CN": "显示类型"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": "date",
+ "type": "string",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "year",
+ "value": "year"
+ },
+ {
+ "label": "years",
+ "value": "years"
+ },
+ {
+ "label": "month",
+ "value": "month"
+ },
+ {
+ "label": "months",
+ "value": "months"
+ },
+ {
+ "label": "date",
+ "value": "date"
+ },
+ {
+ "label": "dates",
+ "value": "dates"
+ },
+ {
+ "label": "datetime",
+ "value": "datetime"
+ },
+ {
+ "label": "week",
+ "value": "week"
+ },
+ {
+ "label": "datetimerange",
+ "value": "datetimerange"
+ },
+ {
+ "label": "daterange",
+ "value": "daterange"
+ },
+ {
+ "label": "monthrange",
+ "value": "monthrange"
+ },
+ {
+ "label": "yearrange",
+ "value": "yearrange"
+ }
+ ]
+ }
+ },
+ "device": []
+ },
+ {
+ "property": "popper-class",
+ "label": {
+ "text": {
+ "zh_CN": "下拉框类名"
+ }
+ },
+ "description": {
+ "zh_CN": "DatePicker 下拉框的类名"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": "",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "双向绑定值改变时触发"
+ },
+ "description": {
+ "zh_CN": "双向绑定值改变时触发"
+ }
+ },
+ "onChange": {
+ "label": {
+ "zh_CN": "用户确认选定的值时触发"
+ },
+ "description": {
+ "zh_CN": "用户确认选定的值时触发"
+ },
+ "type": "event",
+ "defaultValue": ""
+ },
+ "onBlur": {
+ "label": {
+ "zh_CN": "在组件 Input 失去焦点时触发"
+ },
+ "description": {
+ "zh_CN": "在组件 Input 失去焦点时触发"
+ },
+ "type": "event",
+ "defaultValue": ""
+ },
+ "onFocus": {
+ "label": {
+ "zh_CN": "在组件 Input 获得焦点时触发"
+ },
+ "description": {
+ "zh_CN": "在组件 Input 获得焦点时触发"
+ },
+ "type": "event",
+ "defaultValue": ""
+ },
+ "onCalendarChange": {
+ "label": {
+ "zh_CN": "在日历所选日期更改时触发"
+ },
+ "description": {
+ "zh_CN": "在日历所选日期更改时触发"
+ },
+ "type": "event",
+ "defaultValue": ""
+ },
+ "onPanelChange": {
+ "label": {
+ "zh_CN": "当日期面板改变时触发。"
+ },
+ "description": {
+ "zh_CN": "当日期面板改变时触发。"
+ },
+ "type": "event",
+ "defaultValue": ""
+ },
+ "onVisibleChange": {
+ "label": {
+ "zh_CN": "当 DatePicker 的下拉列表出现/消失时触发"
+ },
+ "description": {
+ "zh_CN": "当 DatePicker 的下拉列表出现/消失时触发"
+ },
+ "type": "event",
+ "defaultValue": ""
+ }
+ },
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "自定义单元格内容"
+ },
+ "description": {
+ "zh_CN": "自定义单元格内容"
+ }
+ },
+ "range-separator": {
+ "label": {
+ "zh_CN": "自定义范围分割符内容"
+ },
+ "description": {
+ "zh_CN": "自定义范围分割符内容"
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "按钮"
+ },
+ "component": "ElButton",
+ "icon": "button",
+ "description": "常用的操作按钮",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElButton",
+ "destructuring": true
+ },
+ "group": "基础组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": true,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "type",
+ "size"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "尺寸"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "default",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "large",
+ "value": "large"
+ },
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "type",
+ "label": {
+ "text": {
+ "zh_CN": "类型"
+ }
+ },
+ "description": {
+ "zh_CN": "类型"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "plain",
+ "label": {
+ "text": {
+ "zh_CN": "朴素按钮"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为朴素按钮"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "text",
+ "label": {
+ "text": {
+ "zh_CN": "文字按钮"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为文字按钮"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "bg",
+ "label": {
+ "text": {
+ "zh_CN": "背景颜色"
+ }
+ },
+ "description": {
+ "zh_CN": "是否显示文字按钮背景颜色"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "link",
+ "label": {
+ "text": {
+ "zh_CN": "链接按钮"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为链接按钮"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "round",
+ "label": {
+ "text": {
+ "zh_CN": "圆角按钮"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为圆角按钮"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "circle",
+ "label": {
+ "text": {
+ "zh_CN": "圆形按钮"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为圆形按钮"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "loading",
+ "label": {
+ "text": {
+ "zh_CN": "加载中状态"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为加载中状态"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "disabled",
+ "label": {
+ "text": {
+ "zh_CN": "禁用"
+ }
+ },
+ "description": {
+ "zh_CN": "是否禁用"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {},
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "default"
+ },
+ "description": {
+ "zh_CN": "自定义默认内容"
+ }
+ },
+ "loading": {
+ "label": {
+ "zh_CN": "loading"
+ },
+ "description": {
+ "zh_CN": "自定义加载中组件"
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "表单"
+ },
+ "component": "ElForm",
+ "icon": "form",
+ "description": "表单包含 输入框, 单选框, 下拉选择, 多选框 等用户输入的组件。 使用表单,您可以收集、验证和提交数据。",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElForm",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": true,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": [
+ "ElFormItem"
+ ],
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "inline",
+ "label-width"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "model",
+ "label": {
+ "text": {
+ "zh_CN": "数据对象"
+ }
+ },
+ "description": {
+ "zh_CN": "表单数据对象"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "rules",
+ "label": {
+ "text": {
+ "zh_CN": "验证规则"
+ }
+ },
+ "description": {
+ "zh_CN": "表单验证规则"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "inline",
+ "label": {
+ "text": {
+ "zh_CN": "行内模式"
+ }
+ },
+ "description": {
+ "zh_CN": "行内表单模式"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "label-position",
+ "label": {
+ "text": {
+ "zh_CN": "标签位置"
+ }
+ },
+ "description": {
+ "zh_CN": "表单域标签的位置, 当设置为 left 或 right 时,则也需要设置标签宽度属性"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "right",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "left",
+ "value": "left"
+ },
+ {
+ "label": "right",
+ "value": "right"
+ },
+ {
+ "label": "top",
+ "value": "top"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "label-width",
+ "label": {
+ "text": {
+ "zh_CN": "标签宽度"
+ }
+ },
+ "description": {
+ "zh_CN": "标签的长度,例如 '50px'。 作为 Form 直接子元素的 form-item 会继承该值。 可以使用 auto。"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "label-suffix",
+ "label": {
+ "text": {
+ "zh_CN": "标签后缀"
+ }
+ },
+ "description": {
+ "zh_CN": "表单域标签的后缀"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "hide-required-asterisk",
+ "label": {
+ "text": {
+ "zh_CN": "隐藏必填星号"
+ }
+ },
+ "description": {
+ "zh_CN": "是否隐藏必填字段标签旁边的红色星号"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "require-asterisk-position",
+ "label": {
+ "text": {
+ "zh_CN": "星号位置"
+ }
+ },
+ "description": {
+ "zh_CN": "星号的位置"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "left",
+ "widget": {
+ "component": "ButtonGroupConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "left",
+ "value": "left"
+ },
+ {
+ "label": "right",
+ "value": "right"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "show-message",
+ "label": {
+ "text": {
+ "zh_CN": "显示校验信息"
+ }
+ },
+ "description": {
+ "zh_CN": "是否显示校验错误信息"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": true,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "inline-message",
+ "label": {
+ "text": {
+ "zh_CN": "行内显示校验信息"
+ }
+ },
+ "description": {
+ "zh_CN": "是否以行内形式展示校验信息"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "status-icon",
+ "label": {
+ "text": {
+ "zh_CN": "显示校验结果图标"
+ }
+ },
+ "description": {
+ "zh_CN": "是否在输入框中显示校验结果反馈图标"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "validate-on-rule-change",
+ "label": {
+ "text": {
+ "zh_CN": "触发验证"
+ }
+ },
+ "description": {
+ "zh_CN": "是否在 rules 属性改变后立即触发一次验证"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": true,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "用于控制该表单内组件的尺寸"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "default",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "large",
+ "value": "large"
+ },
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "disabled",
+ "label": {
+ "text": {
+ "zh_CN": "禁用"
+ }
+ },
+ "description": {
+ "zh_CN": "是否禁用该表单内的所有组件。 如果设置为 true, 它将覆盖内部组件的 disabled 属性"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "scroll-to-error",
+ "label": {
+ "text": {
+ "zh_CN": "滚动到错误项"
+ }
+ },
+ "description": {
+ "zh_CN": "当校验失败时,滚动到第一个错误表单项"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ },
+ "device": []
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {
+ "onValidate": {
+ "label": {
+ "zh_CN": "任一表单项被校验后触发"
+ },
+ "description": {
+ "zh_CN": "任一表单项被校验后触发"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ },
+ "defaultValue": ""
+ }
+ },
+ "slots": {}
+ }
+ },
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "表单子项"
+ },
+ "component": "ElFormItem",
+ "icon": "formItem",
+ "description": "表单项,用于包裹表单控件并展示标签与校验信息,需作为 ElForm 的子节点。",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElFormItem",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": true,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": [
+ "ElForm"
+ ],
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "prop",
+ "label",
+ "required"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "prop",
+ "label": {
+ "text": {
+ "zh_CN": "键名"
+ }
+ },
+ "description": {
+ "zh_CN": "model 的键名。 它可以是一个属性的值(如 a.b.0 或 [a', 'b', '0'])。 在定义了 validate、resetFields 的方法时,该属性是必填的"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "label",
+ "label": {
+ "text": {
+ "zh_CN": "标签文本"
+ }
+ },
+ "description": {
+ "zh_CN": "标签文本"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "label-width",
+ "label": {
+ "text": {
+ "zh_CN": "标签宽度"
+ }
+ },
+ "description": {
+ "zh_CN": "标签宽度,例如 '50px'。 可以使用 auto"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "required",
+ "label": {
+ "text": {
+ "zh_CN": "必填项"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为必填项,如不设置,则会根据校验规则确认"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "rules",
+ "label": {
+ "text": {
+ "zh_CN": "验证规则"
+ }
+ },
+ "description": {
+ "zh_CN": "表单验证规则, 更多内容可以参考async-validator"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "error",
+ "label": {
+ "text": {
+ "zh_CN": "错误信息"
+ }
+ },
+ "description": {
+ "zh_CN": "表单域验证错误时的提示信息。设置该值会导致表单验证状态变为 error,并显示该错误信息"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "show-message",
+ "label": {
+ "text": {
+ "zh_CN": "显示错误信息"
+ }
+ },
+ "description": {
+ "zh_CN": "是否显示校验错误信息"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "inline-message",
+ "label": {
+ "text": {
+ "zh_CN": "行内显示错误信息"
+ }
+ },
+ "description": {
+ "zh_CN": "是否在行内显示校验信息"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "用于控制该表单内组件的尺寸"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "default",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "large",
+ "value": "large"
+ },
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "for",
+ "label": {
+ "text": {
+ "zh_CN": "for"
+ }
+ },
+ "description": {
+ "zh_CN": "和原生标签相同能力"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "validate-status",
+ "label": {
+ "text": {
+ "zh_CN": "校验状态"
+ }
+ },
+ "description": {
+ "zh_CN": "formItem 校验的状态"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "error",
+ "value": "error"
+ },
+ {
+ "label": "validating",
+ "value": "validating"
+ },
+ {
+ "label": "success",
+ "value": "success"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {},
+ "slots": {
+ "label": {
+ "label": {
+ "zh_CN": "label"
+ },
+ "description": {
+ "zh_CN": "标签位置显示的内容"
+ }
+ },
+ "error": {
+ "label": {
+ "zh_CN": "error"
+ },
+ "description": {
+ "zh_CN": "验证错误信息的显示内容"
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "表格"
+ },
+ "component": "ElTable",
+ "icon": "table",
+ "description": "用于展示多条结构类似的数据, 可对数据进行排序、筛选、对比或其他自定义操作",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElTable",
+ "destructuring": true
+ },
+ "group": "数据展示",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": [
+ "ElTableColumn"
+ ],
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "data",
+ "stripe",
+ "border"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "description": {
+ "zh_CN": "显示的数据"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "columns",
+ "label": {
+ "text": {
+ "zh_CN": "表格列配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "type",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "type"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "对应列的类型。 如果设置了selection则显示多选框; 如果设置了 index 则显示该行的索引(从 1 开始计算); 如果设置了 expand 则显示为一个可展开的按钮"
+ }
+ },
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "selection",
+ "value": "selection"
+ },
+ {
+ "label": "index",
+ "value": "index"
+ },
+ {
+ "label": "expand",
+ "value": "expand"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "index",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "index"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "如果设置了 type=index,可以通过传递 index 属性来自定义索引"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "label",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "label"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "显示的标题"
+ }
+ },
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "column-key",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "column-key"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "column 的 key, column 的 key, 如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件"
+ }
+ },
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "prop",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "prop"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "字段名称 对应列内容的字段名, 也可以使用 property属性"
+ }
+ },
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "width",
+ "type": "number",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "width"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "对应列的宽度"
+ }
+ },
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "min-width",
+ "type": "number",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "min-width"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "对应列的最小宽度, 对应列的最小宽度, 与 width 的区别是 width 是固定的,min-width 会把剩余宽度按比例分配给设置了 min-width 的列"
+ }
+ },
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "fixed",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "fixed"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "列是否固定在左侧或者右侧。 true 表示固定在左侧"
+ }
+ },
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "left",
+ "value": "left"
+ },
+ {
+ "label": "right",
+ "value": "right"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "sortable",
+ "type": "boolean",
+ "labelPosition": "left",
+ "label": {
+ "text": {
+ "zh_CN": "sortable"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "对应列是否可以排序"
+ }
+ },
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "sort-method",
+ "type": "function",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "sort-method"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "指定数据按照哪个属性进行排序,仅当sortable设置为true的时候有效。 应该如同 Array.sort 那样返回一个 Number"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "sort-by",
+ "type": "array",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "sort-by"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "指定数据按照哪个属性进行排序,仅当 sortable 设置为 true 且没有设置 sort-method 的时候有效。 如果 sort-by 为数组,则先按照第 1 个属性排序,如果第 1 个相等,再按照第 2 个排序,以此类推"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "sort-orders",
+ "type": "array",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "sort-orders"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "数据在排序时所使用排序策略的轮转顺序,仅当 sortable 为 true 时有效。 需传入一个数组,随着用户点击表头,该列依次按照数组中元素的顺序进行排序"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "resizable",
+ "type": "boolean",
+ "labelPosition": "left",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "resizable"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)"
+ }
+ },
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "formatter",
+ "type": "function",
+ "labelPosition": "top",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "formatter"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "用来格式化内容"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "dataType": "JSFunction"
+ }
+ }
+ },
+ {
+ "property": "show-overflow-tooltip",
+ "type": "boolean",
+ "labelPosition": "left",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "show-overflow-tooltip"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "当内容过长被隐藏时显示 tooltip"
+ }
+ },
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "align",
+ "type": "string",
+ "labelPosition": "top",
+ "defaultValue": "left",
+ "label": {
+ "text": {
+ "zh_CN": "align"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "对齐方式"
+ }
+ },
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "left",
+ "value": "left"
+ },
+ {
+ "label": "center",
+ "value": "center"
+ },
+ {
+ "label": "right",
+ "value": "right"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "header-align",
+ "type": "string",
+ "labelPosition": "top",
+ "defaultValue": "left",
+ "label": {
+ "text": {
+ "zh_CN": "header-align"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "表头对齐方式, 若不设置该项,则使用表格的对齐方式"
+ }
+ },
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "left",
+ "value": "left"
+ },
+ {
+ "label": "center",
+ "value": "center"
+ },
+ {
+ "label": "right",
+ "value": "right"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "class-name",
+ "type": "string",
+ "labelPosition": "top",
+ "defaultValue": "left",
+ "label": {
+ "text": {
+ "zh_CN": "class-name"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "列的 className"
+ }
+ },
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "label-class-name",
+ "type": "string",
+ "labelPosition": "top",
+ "defaultValue": "left",
+ "label": {
+ "text": {
+ "zh_CN": "label-class-name"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "当前列标题的自定义类名"
+ }
+ },
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "selectable",
+ "type": "function",
+ "labelPosition": "top",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "selectable"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "仅对 type=selection 的列有效,类型为 Function,Function 的返回值用来决定这一行的 CheckBox 是否可以勾选"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "reserve-selection",
+ "type": "boolean",
+ "labelPosition": "left",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "reserve-selection"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "数据刷新后是否保留选项,仅对 type=selection 的列有效, 请注意, 需指定 row-key 来让这个功能生效。"
+ }
+ },
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "filters",
+ "type": "array",
+ "labelPosition": "top",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "filters"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "数据刷新后是否保留选项,仅对 type=selection 的列有效, 请注意, 需指定 row-key 来让这个功能生效。"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ },
+ {
+ "property": "filter-placement",
+ "type": "string",
+ "labelPosition": "top",
+ "label": {
+ "text": {
+ "zh_CN": "filter-placement"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "过滤弹出框的定位"
+ }
+ },
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "filter-multiple",
+ "type": "string",
+ "labelPosition": "left",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "filter-multiple"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "数据过滤的选项是否多选"
+ }
+ },
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "filter-method",
+ "type": "function",
+ "labelPosition": "top",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "filter-method"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "数据过滤使用的方法, 如果是多选的筛选项,对每一条数据会执行多次,任意一次返回 true 就会显示"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "filtered-value",
+ "type": "array",
+ "labelPosition": "top",
+ "defaultValue": true,
+ "label": {
+ "text": {
+ "zh_CN": "filtered-value"
+ }
+ },
+ "description": {
+ "text": {
+ "zh_CN": "选中的数据过滤项,如果需要自定义表头过滤的渲染方式,可能会需要此属性"
+ }
+ },
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "TableColumnsConfigurator",
+ "props": {
+ "type": "object",
+ "textField": "label",
+ "language": "json",
+ "buttonText": "编辑列配置",
+ "title": "编辑列配置",
+ "expand": true
+ }
+ },
+ "description": {
+ "zh_CN": "表格列的配置信息"
+ },
+ "labelPosition": "top"
+ },
+ {
+ "property": "max-height",
+ "label": {
+ "text": {
+ "zh_CN": "最大高度"
+ }
+ },
+ "description": {
+ "zh_CN": "Table 的最大高度。"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "height",
+ "label": {
+ "text": {
+ "zh_CN": "表格高度"
+ }
+ },
+ "description": {
+ "zh_CN": "Table 的高度, 默认为自动高度。 这个高度会设置为 Table 的 style.height 的值,Table 的高度会受控于外部样式。"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "stripe",
+ "label": {
+ "text": {
+ "zh_CN": "斑马纹"
+ }
+ },
+ "description": {
+ "zh_CN": "是否为斑马纹 table"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "border",
+ "label": {
+ "text": {
+ "zh_CN": "纵向边框"
+ }
+ },
+ "description": {
+ "zh_CN": "是否带有纵向边框"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "表格尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "Table 的尺寸"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "default",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "large",
+ "value": "large"
+ },
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "property": "fit",
+ "label": {
+ "text": {
+ "zh_CN": "列宽自撑开"
+ }
+ },
+ "description": {
+ "zh_CN": "列的宽度是否自撑开"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": true,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "show-header",
+ "label": {
+ "text": {
+ "zh_CN": "显示表头"
+ }
+ },
+ "description": {
+ "zh_CN": "是否显示表头"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": true,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "highlight-current-row",
+ "label": {
+ "text": {
+ "zh_CN": "高亮当前行"
+ }
+ },
+ "description": {
+ "zh_CN": "是否要高亮当前行"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "current-row-key",
+ "label": {
+ "text": {
+ "zh_CN": "当前行的 key"
+ }
+ },
+ "description": {
+ "zh_CN": "当前行的 key,只写属性"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "row-class-name",
+ "label": {
+ "text": {
+ "zh_CN": "行的类名"
+ }
+ },
+ "description": {
+ "zh_CN": "行的 className"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "row-key",
+ "label": {
+ "text": {
+ "zh_CN": "行数据的 Key"
+ }
+ },
+ "description": {
+ "zh_CN": "行数据的 Key,用来优化 Table 的渲染; 在使用reserve-selection功能与显示树形数据时,该属性是必填的。 类型为 String 时,支持多层访问:user.info.id,但不支持 user.info[0].id,此种情况请使用 Function"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "empty-text",
+ "label": {
+ "text": {
+ "zh_CN": "空数据文本"
+ }
+ },
+ "description": {
+ "zh_CN": "空数据时显示的文本内容"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "device": []
+ },
+ {
+ "property": "table-layout",
+ "label": {
+ "text": {
+ "zh_CN": "表格布局方式"
+ }
+ },
+ "description": {
+ "zh_CN": "设置表格单元、行和列的布局方式"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "top",
+ "defaultValue": "fixed",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "fixed",
+ "value": "fixed"
+ },
+ {
+ "label": "auto",
+ "value": "auto"
+ }
+ ]
+ }
+ },
+ "device": []
+ },
+ {
+ "property": "scrollbar-always-on",
+ "label": {
+ "text": {
+ "zh_CN": "显示滚动条"
+ }
+ },
+ "description": {
+ "zh_CN": "总是显示滚动条"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "flexible",
+ "label": {
+ "text": {
+ "zh_CN": "主轴最小尺寸"
+ }
+ },
+ "description": {
+ "zh_CN": "确保主轴的最小尺寸,以便不超过内容"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "defaultValue": false,
+ "type": "boolean",
+ "widget": {
+ "component": "CheckBoxConfigurator",
+ "props": {}
+ }
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {
+ "onSelect": {
+ "label": {
+ "zh_CN": "勾选数据行的 Checkbox 时触发"
+ },
+ "description": {
+ "zh_CN": "当用户手动勾选数据行的 Checkbox 时触发的事件"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "selection",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前选中项"
+ }
+ },
+ {
+ "name": "row",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前行"
+ }
+ }
+ ],
+ "returns": {}
+ }
+ },
+ "onSelectAll": {
+ "label": {
+ "zh_CN": "勾选全选时触发"
+ },
+ "description": {
+ "zh_CN": "当用户手动勾选全选 Checkbox 时触发的事件"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "selection",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前选中项"
+ }
+ }
+ ],
+ "returns": {}
+ }
+ },
+ "onSelectionChange": {
+ "label": {
+ "zh_CN": "选择项发生变化时会触发"
+ },
+ "description": {
+ "zh_CN": "当选择项发生变化时会触发该事件"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "selection",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前选中项"
+ }
+ }
+ ],
+ "returns": {}
+ }
+ },
+ "onCellMouseEnter": {
+ "label": {
+ "zh_CN": "单元格 hover 时会触发"
+ },
+ "description": {
+ "zh_CN": "当单元格 hover 进入时会触发该事件"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "row",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前行"
+ }
+ },
+ {
+ "name": "column",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前列"
+ }
+ },
+ {
+ "name": "cell",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前单元格"
+ }
+ },
+ {
+ "name": "event",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "原生事件 event"
+ }
+ }
+ ],
+ "returns": {}
+ }
+ },
+ "onCellMouseLeave": {
+ "label": {
+ "zh_CN": "单元格 hover 退出时会触发"
+ },
+ "description": {
+ "zh_CN": "当单元格 hover 退出时会触发该事件"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "row",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前行"
+ }
+ },
+ {
+ "name": "column",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前列"
+ }
+ },
+ {
+ "name": "cell",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前单元格"
+ }
+ },
+ {
+ "name": "event",
+ "type": "Object",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "原生事件 event"
+ }
+ }
+ ],
+ "returns": {}
+ }
+ }
+ },
+ "slots": {
+ "empty": {
+ "label": {
+ "zh_CN": "empty"
+ },
+ "description": {
+ "zh_CN": "当数据为空时自定义的内容"
+ }
+ },
+ "append": {
+ "label": {
+ "zh_CN": "append"
+ },
+ "description": {
+ "zh_CN": "插入至表格最后一行之后的内容, 如果需要对表格的内容进行无限滚动操作,可能需要用到这个 slot。 若表格有合计行,该 slot 会位于合计行之上。"
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 1,
+ "version": "2.4.2",
+ "name": {
+ "zh_CN": "表格列"
+ },
+ "component": "ElTableColumn",
+ "icon": "table",
+ "description": "表格的列,用于定义列标题、字段映射及自定义单元格内容",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElTableColumn",
+ "destructuring": true
+ },
+ "group": "数据展示",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "isPopper": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": [
+ "ElTable"
+ ],
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": [
+ "prop",
+ "label",
+ "width"
+ ]
+ },
+ "contextMenu": {
+ "actions": [
+ "copy",
+ "remove",
+ "insert",
+ "updateAttr",
+ "bindEvent",
+ "createBlock"
+ ],
+ "disable": []
+ },
+ "invalidity": [
+ ""
+ ],
+ "clickCapture": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "prop",
+ "label": {
+ "text": {
+ "zh_CN": "字段名"
+ }
+ },
+ "description": {
+ "zh_CN": "对应列内容的字段名"
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "label",
+ "label": {
+ "text": {
+ "zh_CN": "列标题"
+ }
+ },
+ "description": {
+ "zh_CN": "显示的标题"
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "width",
+ "label": {
+ "text": {
+ "zh_CN": "列宽度"
+ }
+ },
+ "description": {
+ "zh_CN": "对应列的宽度"
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ }
+ },
+ {
+ "property": "align",
+ "label": {
+ "text": {
+ "zh_CN": "对齐方式"
+ }
+ },
+ "description": {
+ "zh_CN": "对齐方式"
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "labelPosition": "left",
+ "type": "string",
+ "defaultValue": "left",
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "left",
+ "value": "left"
+ },
+ {
+ "label": "center",
+ "value": "center"
+ },
+ {
+ "label": "right",
+ "value": "right"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "description": {
+ "zh_CN": ""
+ }
+ }
+ ],
+ "events": {},
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "default"
+ },
+ "description": {
+ "zh_CN": "自定义列内容。插槽参数为 row(行数据)、column(列配置)、$index(行索引)。请使用 Template 组件包裹子节点;表达式中直接使用 row;事件处理请使用 JSExpression 箭头函数通过闭包引用 row,例如 () => { this.handleEdit(row); },不要使用 Slot 组件或 scope.row"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "卡片"
+ },
+ "component": "ElCard",
+ "icon": "card",
+ "description": "Element Plus 卡片,用于包裹展示内容",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElCard",
+ "destructuring": true
+ },
+ "group": "布局组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": true,
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "header",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "卡片标题"
+ }
+ }
+ },
+ {
+ "property": "shadow",
+ "type": "string",
+ "defaultValue": "always",
+ "label": {
+ "text": {
+ "zh_CN": "阴影"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "默认插槽"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "栅格行"
+ },
+ "component": "ElRow",
+ "icon": "row",
+ "description": "Element Plus 栅格行",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElRow",
+ "destructuring": true
+ },
+ "group": "布局组件",
+ "category": "element-plus",
+ "configure": {
+ "isContainer": true,
+ "framework": "Vue",
+ "nestingRule": {
+ "childWhitelist": [
+ "ElCol"
+ ],
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ }
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "gutter",
+ "type": "number",
+ "label": {
+ "text": {
+ "zh_CN": "栅格间隔"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "栅格列"
+ },
+ "component": "ElCol",
+ "icon": "col",
+ "description": "Element Plus 栅格列,需作为 ElRow 的子节点",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElCol",
+ "destructuring": true
+ },
+ "group": "布局组件",
+ "category": "element-plus",
+ "configure": {
+ "isContainer": true,
+ "framework": "Vue",
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": [
+ "ElRow"
+ ],
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ }
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "span",
+ "type": "number",
+ "defaultValue": 12,
+ "label": {
+ "text": {
+ "zh_CN": "占据列数"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "选择器"
+ },
+ "component": "ElSelect",
+ "icon": "select",
+ "description": "Element Plus 下拉选择",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElSelect",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "loop": true,
+ "isContainer": true,
+ "framework": "Vue",
+ "nestingRule": {
+ "childWhitelist": [
+ "ElOption"
+ ],
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ }
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ }
+ },
+ {
+ "property": "placeholder",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "占位文本"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "值变化"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "选项"
+ },
+ "component": "ElOption",
+ "icon": "option",
+ "description": "Element Plus 下拉选项,需作为 ElSelect 的子节点",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElOption",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "framework": "Vue",
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": [
+ "ElSelect"
+ ],
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ }
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "label",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "显示文本"
+ }
+ }
+ },
+ {
+ "property": "value",
+ "type": "string",
+ "defaultValue": "",
+ "label": {
+ "text": {
+ "zh_CN": "选项值"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "单选框"
+ },
+ "component": "ElRadio",
+ "icon": "radio",
+ "description": "Element Plus 单选框,需作为 ElRadioGroup 的子节点",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElRadio",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "framework": "Vue",
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": [
+ "ElRadioGroup"
+ ],
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ }
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "value",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "选项值"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "显示文本"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "单选组"
+ },
+ "component": "ElRadioGroup",
+ "icon": "radio-group",
+ "description": "Element Plus 单选组",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElRadioGroup",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "isContainer": true,
+ "framework": "Vue",
+ "nestingRule": {
+ "childWhitelist": [
+ "ElRadio"
+ ],
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ }
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "值变化"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "开关"
+ },
+ "component": "ElSwitch",
+ "icon": "switch",
+ "description": "Element Plus 开关",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElSwitch",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "值变化"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "复选框"
+ },
+ "component": "ElCheckbox",
+ "icon": "checkbox",
+ "description": "Element Plus 复选框",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElCheckbox",
+ "destructuring": true
+ },
+ "group": "表单组件",
+ "category": "element-plus",
+ "configure": {
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ }
+ },
+ {
+ "property": "label",
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "显示文本"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "值变化"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "标签"
+ },
+ "component": "ElTag",
+ "icon": "tag",
+ "description": "Element Plus 标签",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElTag",
+ "destructuring": true
+ },
+ "group": "数据展示",
+ "category": "element-plus",
+ "configure": {
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "type",
+ "type": "string",
+ "defaultValue": "primary",
+ "label": {
+ "text": {
+ "zh_CN": "类型"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "默认插槽"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "分割线"
+ },
+ "component": "ElDivider",
+ "icon": "divider",
+ "description": "Element Plus 分割线",
+ "npm": {
+ "package": "element-plus",
+ "exportName": "ElDivider",
+ "destructuring": true
+ },
+ "group": "布局组件",
+ "category": "element-plus",
+ "configure": {
+ "framework": "Vue"
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "contentPosition",
+ "type": "string",
+ "defaultValue": "center",
+ "label": {
+ "text": {
+ "zh_CN": "内容位置"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ],
+ "blocks": [],
+ "snippets": [
+ {
+ "group": "layout",
+ "label": {
+ "zh_CN": "布局与容器"
+ },
+ "children": [
+ {
+ "name": {
+ "zh_CN": "栅格布局"
+ },
+ "icon": "row",
+ "screenshot": "",
+ "snippetName": "ElRow",
+ "schema": {
+ "componentName": "ElRow",
+ "props": {
+ "gutter": 12
+ },
+ "children": [
+ {
+ "componentName": "ElCol",
+ "props": {
+ "span": 12
+ }
+ },
+ {
+ "componentName": "ElCol",
+ "props": {
+ "span": 12
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "group": "form",
+ "label": {
+ "zh_CN": "表单"
+ },
+ "children": [
+ {
+ "name": {
+ "zh_CN": "基础表单"
+ },
+ "icon": "form",
+ "screenshot": "",
+ "snippetName": "ElForm",
+ "schema": {
+ "componentName": "ElForm",
+ "props": {
+ "labelPosition": "top"
+ },
+ "children": [
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "姓名",
+ "prop": "name"
+ },
+ "children": [
+ {
+ "componentName": "ElInput",
+ "props": {
+ "placeholder": "请输入"
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "children": [
+ {
+ "componentName": "ElButton",
+ "props": {
+ "type": "primary"
+ },
+ "children": "提交"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "group": "table",
+ "label": {
+ "zh_CN": "表格"
+ },
+ "children": [
+ {
+ "name": {
+ "zh_CN": "基础表格"
+ },
+ "icon": "table",
+ "screenshot": "",
+ "snippetName": "ElTable",
+ "schema": {
+ "componentName": "ElTable",
+ "props": {
+ "data": [],
+ "stripe": true,
+ "style": "width: 100%;"
+ },
+ "children": [
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "name",
+ "label": "姓名",
+ "width": 120
+ }
+ },
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "id",
+ "label": "工号",
+ "width": 100
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "group": "card",
+ "label": {
+ "zh_CN": "卡片"
+ },
+ "children": [
+ {
+ "name": {
+ "zh_CN": "基础卡片"
+ },
+ "snippetName": "ElCard",
+ "schema": {
+ "componentName": "ElCard",
+ "props": {
+ "header": "卡片标题",
+ "shadow": "hover"
+ },
+ "children": [
+ {
+ "componentName": "p",
+ "children": "卡片内容区域"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "group": "table",
+ "label": {
+ "zh_CN": "表格"
+ },
+ "children": [
+ {
+ "name": {
+ "zh_CN": "操作列"
+ },
+ "snippetName": "ElTableColumn",
+ "schema": {
+ "componentName": "ElTableColumn",
+ "props": {
+ "label": "操作",
+ "width": 160,
+ "align": "center",
+ "fixed": "right"
+ },
+ "children": [
+ {
+ "componentName": "Template",
+ "props": {
+ "slot": "default"
+ },
+ "children": [
+ {
+ "componentName": "ElButton",
+ "props": {
+ "type": "primary",
+ "size": "small",
+ "text": true,
+ "onClick": {
+ "type": "JSExpression",
+ "value": "() => { this.handleEdit(row); }"
+ }
+ },
+ "children": "编辑"
+ },
+ {
+ "componentName": "ElButton",
+ "props": {
+ "type": "danger",
+ "size": "small",
+ "text": true,
+ "onClick": {
+ "type": "JSExpression",
+ "value": "() => { this.handleDelete(row); }"
+ }
+ },
+ "children": "删除"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/packages/materials/vue-element-plus/src/meta/meta.ts b/packages/materials/vue-element-plus/src/meta/meta.ts
new file mode 100644
index 00000000..05511d25
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/meta.ts
@@ -0,0 +1,18 @@
+import type { IMaterialsMeta, IExample, IMaterialsProtocol } from '@opentiny/genui-sdk-core';
+import bundleJson from './materials/bundle.json' with { type: 'json' };
+import { examples as allExamples } from './example-schema';
+import { whiteList } from './white-list';
+
+const metaMaterials = [bundleJson] as IMaterialsProtocol[];
+
+function filterExamples(ids: string[]) {
+ return allExamples.filter((example): example is IExample => !!example.id && ids.includes(example.id));
+}
+
+export const materialsMeta: IMaterialsMeta = {
+ materials: metaMaterials,
+ wrapperComponent: 'ElCard',
+ whiteList,
+ examples: filterExamples(['form', 'info', 'table']),
+ rules: [],
+};
diff --git a/packages/materials/vue-element-plus/src/meta/white-list.ts b/packages/materials/vue-element-plus/src/meta/white-list.ts
new file mode 100644
index 00000000..8d84d008
--- /dev/null
+++ b/packages/materials/vue-element-plus/src/meta/white-list.ts
@@ -0,0 +1,40 @@
+export const whiteList = [
+ 'ElInput',
+ 'ElDatePicker',
+ 'ElButton',
+ 'ElForm',
+ 'ElFormItem',
+ 'ElTable',
+ 'ElTableColumn',
+ 'ElCard',
+ 'ElRow',
+ 'ElCol',
+ 'ElSelect',
+ 'ElOption',
+ 'ElRadio',
+ 'ElRadioGroup',
+ 'ElSwitch',
+ 'ElCheckbox',
+ 'ElTag',
+ 'ElDivider',
+ 'ElTabs',
+ 'ElTabPane',
+ 'a',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'h6',
+ 'p',
+ 'ol',
+ 'ul',
+ 'li',
+ 'label',
+ 'div',
+ 'Slot',
+ 'Template',
+ 'Text',
+ 'Icon',
+ 'Img',
+];
diff --git a/packages/materials/vue-element-plus/test/App.vue b/packages/materials/vue-element-plus/test/App.vue
new file mode 100644
index 00000000..8f28a9da
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/App.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
diff --git a/packages/materials/vue-element-plus/test/index.html b/packages/materials/vue-element-plus/test/index.html
new file mode 100644
index 00000000..747e591c
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ vue-element-plus 物料验证
+
+
+
+
+
+
diff --git a/packages/materials/vue-element-plus/test/main.ts b/packages/materials/vue-element-plus/test/main.ts
new file mode 100644
index 00000000..2665b4ab
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/main.ts
@@ -0,0 +1,6 @@
+import { createApp } from 'vue';
+import 'element-plus/dist/index.css';
+import App from './App.vue';
+import './style.css';
+
+createApp(App).mount('#app');
diff --git a/packages/materials/vue-element-plus/test/mock/form-binding.json b/packages/materials/vue-element-plus/test/mock/form-binding.json
new file mode 100644
index 00000000..a6149f30
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/mock/form-binding.json
@@ -0,0 +1,244 @@
+{
+ "componentName": "Page",
+ "state": {
+ "defaultFormData": {
+ "name": "",
+ "sex": "男",
+ "department": "",
+ "protocolStart": "",
+ "email": ""
+ },
+ "formData": {
+ "name": "张三",
+ "sex": "男",
+ "department": "HR",
+ "protocolStart": "2023-01-01",
+ "email": "zhangsan@example.com"
+ },
+ "submitResult": ""
+ },
+ "methods": {
+ "handleSubmit": {
+ "type": "JSFunction",
+ "value": "function handleSubmit() { this.state.submitResult = '已提交:' + JSON.stringify(this.state.formData); }"
+ },
+ "handleReset": {
+ "type": "JSFunction",
+ "value": "function handleReset() { this.state.formData = JSON.parse(JSON.stringify(this.state.defaultFormData)); this.state.submitResult = ''; }"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElCard",
+ "props": {
+ "header": "员工信息表单(双向绑定)",
+ "style": "max-width: 520px; margin: 0 auto;"
+ },
+ "children": [
+ {
+ "componentName": "ElForm",
+ "props": {
+ "model": {
+ "type": "JSExpression",
+ "value": "this.state.formData"
+ },
+ "labelPosition": "top"
+ },
+ "children": [
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "姓名",
+ "prop": "name",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "ElInput",
+ "props": {
+ "placeholder": "请输入姓名",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.name"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "性别",
+ "prop": "sex"
+ },
+ "children": [
+ {
+ "componentName": "ElRadioGroup",
+ "props": {
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.sex"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElRadio",
+ "props": {
+ "value": "男"
+ },
+ "children": "男"
+ },
+ {
+ "componentName": "ElRadio",
+ "props": {
+ "value": "女"
+ },
+ "children": "女"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "部门",
+ "prop": "department",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "ElSelect",
+ "props": {
+ "placeholder": "请选择部门",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.department"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElOption",
+ "props": {
+ "label": "人事部",
+ "value": "HR"
+ }
+ },
+ {
+ "componentName": "ElOption",
+ "props": {
+ "label": "技术部",
+ "value": "tech"
+ }
+ },
+ {
+ "componentName": "ElOption",
+ "props": {
+ "label": "产品部",
+ "value": "product"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "入职日期",
+ "prop": "protocolStart"
+ },
+ "children": [
+ {
+ "componentName": "ElDatePicker",
+ "props": {
+ "type": "date",
+ "placeholder": "请选择日期",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.protocolStart"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "邮箱",
+ "prop": "email"
+ },
+ "children": [
+ {
+ "componentName": "ElInput",
+ "props": {
+ "type": "email",
+ "placeholder": "请输入邮箱",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.email"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "children": [
+ {
+ "componentName": "div",
+ "props": {
+ "style": "display: flex; gap: 12px; justify-content: flex-end;"
+ },
+ "children": [
+ {
+ "componentName": "ElButton",
+ "props": {
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { this.handleReset(); }"
+ }
+ },
+ "children": "重置"
+ },
+ {
+ "componentName": "ElButton",
+ "props": {
+ "type": "primary",
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { this.handleSubmit(); }"
+ }
+ },
+ "children": "提交"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElFormItem",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "this.state.submitResult"
+ },
+ "style": "color: #606266; white-space: pre-wrap;"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/test/mock/index.ts b/packages/materials/vue-element-plus/test/mock/index.ts
new file mode 100644
index 00000000..df96f845
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/mock/index.ts
@@ -0,0 +1,17 @@
+import formBindingSchema from './form-binding.json';
+import tableSchema from './table.json';
+import infoCardSchema from './info-card.json';
+import tabsSchema from './tabs.json';
+
+export interface DemoItem {
+ id: string;
+ label: string;
+ schema: Record;
+}
+
+export const demos: DemoItem[] = [
+ { id: 'form-binding', label: '表单双向绑定', schema: formBindingSchema },
+ { id: 'table', label: '表格渲染', schema: tableSchema },
+ { id: 'info-card', label: '信息展示卡片', schema: infoCardSchema },
+ { id: 'tabs', label: 'Tabs 渲染', schema: tabsSchema },
+];
diff --git a/packages/materials/vue-element-plus/test/mock/info-card.json b/packages/materials/vue-element-plus/test/mock/info-card.json
new file mode 100644
index 00000000..dc02ca14
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/mock/info-card.json
@@ -0,0 +1,78 @@
+{
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "style": "font-size: 14px; font-weight: bold; line-height: 2; margin-bottom: 20px; display: block;",
+ "text": "员工信息详情"
+ }
+ },
+ {
+ "componentName": "ElCard",
+ "props": {
+ "header": "基本信息",
+ "shadow": "never",
+ "style": "max-width: 480px;"
+ },
+ "children": [
+ {
+ "componentName": "ElRow",
+ "props": { "gutter": 12 },
+ "children": [
+ {
+ "componentName": "ElCol",
+ "props": { "span": 6 },
+ "children": [{ "componentName": "Text", "props": { "text": "姓名" } }]
+ },
+ {
+ "componentName": "ElCol",
+ "props": { "span": 18 },
+ "children": [{ "componentName": "Text", "props": { "text": "张三" } }]
+ }
+ ]
+ },
+ {
+ "componentName": "ElDivider",
+ "props": {}
+ },
+ {
+ "componentName": "ElRow",
+ "props": { "gutter": 12 },
+ "children": [
+ {
+ "componentName": "ElCol",
+ "props": { "span": 6 },
+ "children": [{ "componentName": "Text", "props": { "text": "电话" } }]
+ },
+ {
+ "componentName": "ElCol",
+ "props": { "span": 18 },
+ "children": [{ "componentName": "Text", "props": { "text": "18856254558" } }]
+ }
+ ]
+ },
+ {
+ "componentName": "ElDivider",
+ "props": {}
+ },
+ {
+ "componentName": "ElRow",
+ "props": { "gutter": 12 },
+ "children": [
+ {
+ "componentName": "ElCol",
+ "props": { "span": 6 },
+ "children": [{ "componentName": "Text", "props": { "text": "部门" } }]
+ },
+ {
+ "componentName": "ElCol",
+ "props": { "span": 18 },
+ "children": [{ "componentName": "Text", "props": { "text": "技术部" } }]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/test/mock/table.json b/packages/materials/vue-element-plus/test/mock/table.json
new file mode 100644
index 00000000..97f52b7a
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/mock/table.json
@@ -0,0 +1,120 @@
+{
+ "componentName": "Page",
+ "state": {
+ "tableData": []
+ },
+ "lifeCycles": {
+ "onMounted": {
+ "type": "JSFunction",
+ "value": "function onMounted() { this.state.tableData = [{ id: '001', name: '张三', department: '技术部', email: 'zhangsan@example.com', status: '在职' }, { id: '002', name: '李四', department: '市场部', email: 'lisi@example.com', status: '在职' }, { id: '003', name: '王五', department: '人事部', email: 'wangwu@example.com', status: '离职' }, { id: '004', name: '赵六', department: '财务部', email: 'zhaoliu@example.com', status: '在职' }]; }"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElCard",
+ "props": {
+ "header": "员工列表(表格渲染)"
+ },
+ "children": [
+ {
+ "componentName": "ElTable",
+ "props": {
+ "data": {
+ "type": "JSExpression",
+ "value": "this.state.tableData"
+ },
+ "stripe": true,
+ "border": true,
+ "style": "width: 100%;"
+ },
+ "children": [
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "type": "index",
+ "label": "序号",
+ "width": 60,
+ "align": "center"
+ }
+ },
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "id",
+ "label": "工号",
+ "width": 100,
+ "align": "center"
+ }
+ },
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "name",
+ "label": "姓名",
+ "width": 100,
+ "align": "center"
+ }
+ },
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "department",
+ "label": "部门",
+ "width": 120,
+ "align": "center"
+ }
+ },
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "email",
+ "label": "邮箱",
+ "minWidth": 180
+ }
+ },
+ {
+ "componentName": "ElTableColumn",
+ "props": {
+ "prop": "status",
+ "label": "状态",
+ "width": 100,
+ "align": "center"
+ },
+ "children": [
+ {
+ "componentName": "Template",
+ "props": {
+ "slot": "default"
+ },
+ "children": [
+ {
+ "componentName": "ElTag",
+ "props": {
+ "type": {
+ "type": "JSExpression",
+ "value": "row.status === '在职' ? 'success' : 'info'"
+ },
+ "size": "small"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.status"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/test/mock/tabs.json b/packages/materials/vue-element-plus/test/mock/tabs.json
new file mode 100644
index 00000000..079c20c3
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/mock/tabs.json
@@ -0,0 +1,159 @@
+{
+ "componentName": "Page",
+ "state": {
+ "activeTab": "basic",
+ "formData": {
+ "name": ""
+ }
+ },
+ "methods": {
+ "handleTabChange": {
+ "type": "JSFunction",
+ "value": "function handleTabChange(key) { this.state.activeTab = key; }"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElCard",
+ "props": {
+ "header": "用户信息(Tabs 渲染)"
+ },
+ "children": [
+ {
+ "componentName": "ElTabs",
+ "props": {
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.activeTab"
+ },
+ "onTabChange": {
+ "type": "JSExpression",
+ "value": "this.handleTabChange"
+ }
+ },
+ "children": [
+ {
+ "componentName": "ElTabPane",
+ "props": {
+ "label": "基本信息",
+ "name": "basic"
+ },
+ "children": [
+ {
+ "componentName": "h4",
+ "props": { "style": "margin: 0 0 8px;" },
+ "children": "个人信息"
+ },
+ {
+ "componentName": "p",
+ "props": { "style": "margin: 0; color: #6b7280;" },
+ "children": "这里展示用户的基本信息,如姓名、部门等。"
+ },
+ {
+ "componentName": "ElFormItem",
+ "props": {
+ "label": "姓名",
+ "style": "margin-top: 12px;"
+ },
+ "children": [
+ {
+ "componentName": "ElInput",
+ "props": {
+ "placeholder": "请输入姓名",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.name"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElTabPane",
+ "props": {
+ "label": "详细信息",
+ "name": "detail"
+ },
+ "children": [
+ {
+ "componentName": "h4",
+ "props": { "style": "margin: 0 0 8px;" },
+ "children": "详细资料"
+ },
+ {
+ "componentName": "p",
+ "props": { "style": "margin: 0; color: #6b7280;" },
+ "children": "这里展示用户的详细资料,如联系方式、地址等。"
+ },
+ {
+ "componentName": "ul",
+ "props": {
+ "style": "margin: 12px 0 0; padding-left: 20px; color: #374151;"
+ },
+ "children": [
+ { "componentName": "li", "children": "邮箱:user@example.com" },
+ { "componentName": "li", "children": "电话:13800138000" },
+ { "componentName": "li", "children": "地址:北京市朝阳区" }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "ElTabPane",
+ "props": {
+ "label": "设置",
+ "name": "settings"
+ },
+ "children": [
+ {
+ "componentName": "h4",
+ "props": { "style": "margin: 0 0 8px;" },
+ "children": "系统设置"
+ },
+ {
+ "componentName": "p",
+ "props": { "style": "margin: 0 0 12px; color: #6b7280;" },
+ "children": "这里展示账号相关设置选项。"
+ },
+ {
+ "componentName": "div",
+ "props": { "style": "display: flex; gap: 8px;" },
+ "children": [
+ {
+ "componentName": "ElButton",
+ "props": { "type": "primary" },
+ "children": "保存设置"
+ },
+ {
+ "componentName": "ElButton",
+ "children": "恢复默认"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "p",
+ "props": { "style": "margin: 16px 0 0; font-size: 13px; color: #9ca3af;" },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "'当前激活标签:' + this.state.activeTab"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-element-plus/test/schema-context.ts b/packages/materials/vue-element-plus/test/schema-context.ts
new file mode 100644
index 00000000..6fd74ba5
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/schema-context.ts
@@ -0,0 +1,69 @@
+type SchemaFunction = { type: 'JSFunction'; value: string };
+type SchemaExpression = { type: 'JSExpression'; value: string; params?: string[] };
+
+type SchemaContext = Record & {
+ state?: Record;
+ refs?: Record;
+};
+
+function parseExpression(data: SchemaExpression, scope: Record, ctx: SchemaContext) {
+ const mergeScope = { ...ctx, ...scope, slotScope: scope };
+ let expression = data.value;
+ const params: Record = {};
+ if (data.params?.length) {
+ data.params.forEach((paramName) => {
+ params[paramName] = mergeScope[paramName];
+ });
+ expression = `(e) => {(${expression}).call(this, e, ${data.params.join(',')})}`;
+ }
+ return new Function('$scope', `with($scope || {}) { return ${expression} }`).call(ctx, {
+ ...mergeScope,
+ ...params,
+ });
+}
+
+function parseJSFunction(data: SchemaFunction, scope: Record, ctx: SchemaContext) {
+ if (typeof scope === 'object' && Object.keys(scope).length > 0) {
+ const fn = parseExpression({ type: 'JSExpression', value: data.value }, scope, ctx);
+ return fn.bind(ctx);
+ }
+ const innerFn = new Function(`return ${data.value}`).bind(ctx)();
+ return innerFn.bind(ctx);
+}
+
+export function parseSchemaValue(
+ data: SchemaFunction | SchemaExpression,
+ scope: Record,
+ ctx: SchemaContext,
+) {
+ if (data.type === 'JSExpression') {
+ return parseExpression(data, scope, ctx);
+ }
+ return parseJSFunction(data, scope, ctx);
+}
+
+export function createContext(schema: Record) {
+ const context: SchemaContext = {
+ state: structuredClone((schema.state as Record) ?? {}),
+ refs: structuredClone((schema.refs as Record) ?? {}),
+ };
+
+ const methods = (schema.methods as Record) ?? {};
+ Object.keys(methods).forEach((key) => {
+ context[key] = parseSchemaValue(methods[key], {}, context);
+ });
+
+ const lifeCycles = (schema.lifeCycles as Record) ?? {};
+ Object.keys(lifeCycles).forEach((key) => {
+ context[key] = parseSchemaValue(lifeCycles[key], {}, context);
+ });
+
+ return context;
+}
+
+export function runLifeCycle(context: SchemaContext, name: string) {
+ const fn = context[name];
+ if (typeof fn === 'function') {
+ fn.call(context);
+ }
+}
diff --git a/packages/materials/vue-element-plus/test/style.css b/packages/materials/vue-element-plus/test/style.css
new file mode 100644
index 00000000..e1cba599
--- /dev/null
+++ b/packages/materials/vue-element-plus/test/style.css
@@ -0,0 +1,48 @@
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
+ background: #f5f7fa;
+ color: #303133;
+}
+
+#app {
+ min-height: 100vh;
+}
+
+.app-header {
+ padding: 16px 24px;
+ background: #fff;
+ border-bottom: 1px solid #ebeef5;
+}
+
+.app-header h1 {
+ margin: 0 0 12px;
+ font-size: 18px;
+}
+
+.demo-tabs {
+ display: flex;
+ gap: 8px;
+ flex-wrap: wrap;
+}
+
+.demo-tab {
+ border: 1px solid #dcdfe6;
+ background: #fff;
+ color: #606266;
+ border-radius: 4px;
+ padding: 6px 12px;
+ cursor: pointer;
+}
+
+.demo-tab.active {
+ color: #409eff;
+ border-color: #409eff;
+ background: #ecf5ff;
+}
+
+.app-content {
+ padding: 24px;
+ max-width: 960px;
+ margin: 0 auto;
+}
diff --git a/packages/materials/vue-element-plus/tsconfig.json b/packages/materials/vue-element-plus/tsconfig.json
new file mode 100644
index 00000000..507b519f
--- /dev/null
+++ b/packages/materials/vue-element-plus/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "strict": false,
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "erasableSyntaxOnly": false,
+ "noFallthroughCasesInSwitch": true,
+ "resolveJsonModule": true
+ },
+ "include": ["src/**/*"]
+}
diff --git a/packages/materials/vue-element-plus/vite.config.test.ts b/packages/materials/vue-element-plus/vite.config.test.ts
new file mode 100644
index 00000000..37526189
--- /dev/null
+++ b/packages/materials/vue-element-plus/vite.config.test.ts
@@ -0,0 +1,18 @@
+import path from 'path';
+import { defineConfig } from 'vite';
+import vue from '@vitejs/plugin-vue';
+
+const repoRoot = path.resolve(__dirname, '../../..');
+
+export default defineConfig({
+ root: path.resolve(__dirname, './test'),
+ plugins: [vue()],
+ resolve: {
+ alias: {
+ '@opentiny/tiny-schema-renderer': path.resolve(repoRoot, 'projects/tiny-schema-renderer/index.js'),
+ },
+ },
+ server: {
+ open: true,
+ },
+});
diff --git a/packages/materials/vue-element-plus/vite.config.ts b/packages/materials/vue-element-plus/vite.config.ts
new file mode 100644
index 00000000..296ae7d4
--- /dev/null
+++ b/packages/materials/vue-element-plus/vite.config.ts
@@ -0,0 +1,37 @@
+import path from 'path';
+import { defineConfig } from 'vite';
+import dts from 'vite-plugin-dts';
+import vue from '@vitejs/plugin-vue';
+import escapeStringRegexp from 'escape-string-regexp';
+import packageJson from './package.json';
+import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js';
+
+const externalPackages = [
+ ...Object.keys(packageJson.dependencies || {}),
+ ...Object.keys(packageJson.peerDependencies || {}),
+];
+
+export default defineConfig({
+ plugins: [
+ vue(),
+ dts({
+ rollupTypes: true,
+ }),
+ cssInjectedByJsPlugin(),
+ ],
+ build: {
+ lib: {
+ entry: {
+ index: path.resolve(__dirname, './src/index.ts'),
+ meta: path.resolve(__dirname, './src/meta/index.ts'),
+ materials: path.resolve(__dirname, './src/materials/index.ts'),
+ },
+ formats: ['es'],
+ fileName: (_format, entryName) => `${entryName}.js`,
+ },
+ sourcemap: true,
+ rollupOptions: {
+ external: externalPackages.map((name) => new RegExp(`^${escapeStringRegexp(name)}(/|$)`)),
+ },
+ },
+});
diff --git a/packages/materials/vue-element-plus/vitest.config.ts b/packages/materials/vue-element-plus/vitest.config.ts
new file mode 100644
index 00000000..4ac6027d
--- /dev/null
+++ b/packages/materials/vue-element-plus/vitest.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+ test: {
+ environment: 'node',
+ },
+});
diff --git a/packages/materials/vue-opentiny-vue/README.md b/packages/materials/vue-opentiny-vue/README.md
new file mode 100644
index 00000000..333852bd
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/README.md
@@ -0,0 +1,69 @@
+# @opentiny/genui-sdk-materials-vue-opentiny-vue
+
+
+A GenUI Vue materials package based on [OpenTiny Vue](https://opentiny.design/tiny-vue/), for schema-driven page generation and rendering.
+
+## Install
+
+```bash
+npm install @opentiny/genui-sdk-materials-vue-opentiny-vue @opentiny/genui-sdk-vue @opentiny/genui-sdk-core
+```
+
+## Quick Start
+
+### Frontend Rendering
+
+Inject materials via `ConfigProvider`:
+
+```ts
+import { GenuiConfigProvider, GenuiChat } from '@opentiny/genui-sdk-vue';
+import { materials } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/materials';
+```
+
+```vue
+
+
+
+```
+
+### Generate LLM Prompt (Server)
+
+```ts
+import { genPrompt } from '@opentiny/genui-sdk-core';
+import { materialsMeta } from '@opentiny/genui-sdk-materials-vue-opentiny-vue/meta';
+
+const systemPrompt = genPrompt('Vue', materialsMeta, customConfig);
+```
+
+`materialsMeta.wrapperComponent` defaults to `TinyCard`.
+
+Use `miniMaterials` / `miniMaterialsMeta` when you need a smaller component set (without charts).
+
+## API
+
+| Export Path | Exports | Description |
+|-------------|---------|-------------|
+| `@opentiny/genui-sdk-materials-vue-opentiny-vue` | `materials`, `miniMaterials`, `materialsMeta`, `miniMaterialsMeta` | Unified entry |
+| `.../materials` | `materials`, `miniMaterials` | Inject into `ConfigProvider` for schema rendering |
+| `.../meta` | `materialsMeta`, `miniMaterialsMeta` | For `genPrompt()` / building the server system prompt |
+
+### `materials` / `miniMaterials`
+
+Component registry mapping OpenTiny Vue components, used by the renderer to resolve nodes by `componentName`.
+
+### `materialsMeta` / `miniMaterialsMeta`
+
+Materials metadata, including:
+
+- `materials`: Protocol descriptions for components / blocks / snippets
+- `wrapperComponent`: Default wrapper component (`TinyCard`)
+- `whiteList`: Whitelist of `componentName` values available to the LLM
+- `examples`: Prompt example schemas (form / info / grid / tabs)
+- `rules`: Extra constraint rules
+
+Component library: `@opentiny/vue-*`.
+
+## More
+
+- [GenUI SDK](https://opentiny.design/genui-sdk)
+- [Renderer Guide](https://docs.opentiny.design/genui-sdk/components/renderer)
diff --git a/packages/materials/vue-opentiny-vue/package.json b/packages/materials/vue-opentiny-vue/package.json
index 3a7d2d25..9e87eb83 100644
--- a/packages/materials/vue-opentiny-vue/package.json
+++ b/packages/materials/vue-opentiny-vue/package.json
@@ -1,22 +1,78 @@
{
"name": "@opentiny/genui-sdk-materials-vue-opentiny-vue",
"version": "1.0.0",
+ "description": "GenUI Vue materials package based on OpenTiny Vue",
+ "author": "OpenTiny Team",
+ "license": "MIT",
+ "homepage": "https://opentiny.design/genui-sdk",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/opentiny/genui-sdk",
+ "directory": "packages/materials/vue-opentiny-vue"
+ },
+ "bugs": {
+ "url": "https://github.com/opentiny/genui-sdk/issues"
+ },
+ "keywords": [
+ "genui",
+ "generative-ui",
+ "opentiny",
+ "vue",
+ "materials"
+ ],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
+ "files": [
+ "dist",
+ "README.md"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
"scripts": {
"build": "vite build"
},
"dependencies": {
- "@opentiny/vue-button": "^3.28.0",
- "@opentiny/vue-chart-bar": "~3.14.0",
- "@opentiny/vue-chart-histogram": "~3.14.0",
- "@opentiny/vue-chart-line": "~3.14.0",
- "@opentiny/vue-chart-pie": "~3.14.0",
- "@opentiny/vue-chart-radar": "~3.14.0",
- "@opentiny/vue-chart-ring": "3.14.0",
- "@opentiny/vue-select": "^3.28.0",
- "@opentiny/vue-tabs": "^3.28.0",
+ "@opentiny/genui-sdk-core": "workspace:*",
+ "@opentiny/vue-button": "~3.28.0",
+ "@opentiny/vue-card": "~3.28.0",
+ "@opentiny/vue-carousel": "~3.28.0",
+ "@opentiny/vue-carousel-item": "~3.28.0",
+ "@opentiny/vue-huicharts-line": "3.28.0",
+ "@opentiny/vue-huicharts-histogram": "~3.28.0",
+ "@opentiny/vue-huicharts-bar": "~3.28.0",
+ "@opentiny/vue-huicharts-radar": "~3.28.0",
+ "@opentiny/vue-huicharts-ring": "~3.28.0",
+ "@opentiny/vue-huicharts-pie": "~3.28.0",
+ "@opentiny/vue-huicharts-funnel": "~3.28.0",
+ "@opentiny/vue-huicharts-scatter": "~3.28.0",
+ "@opentiny/vue-huicharts-waterfall": "~3.28.0",
+ "@opentiny/vue-huicharts-gauge": "~3.28.0",
+ "@opentiny/vue-huicharts-graph": "~3.28.0",
+ "@opentiny/vue-huicharts-process": "~3.28.0",
+ "@opentiny/vue-checkbox": "~3.28.0",
+ "@opentiny/vue-checkbox-button": "~3.28.0",
+ "@opentiny/vue-checkbox-group": "~3.28.0",
+ "@opentiny/vue-col": "~3.28.0",
+ "@opentiny/vue-date-picker": "~3.28.0",
+ "@opentiny/vue-form": "~3.28.0",
+ "@opentiny/vue-form-item": "~3.28.0",
+ "@opentiny/vue-grid": "~3.28.0",
+ "@opentiny/vue-input": "~3.28.0",
+ "@opentiny/vue-layout": "~3.28.0",
+ "@opentiny/vue-numeric": "~3.28.0",
+ "@opentiny/vue-pager": "~3.28.0",
+ "@opentiny/vue-radio": "~3.28.0",
+ "@opentiny/vue-radio-group": "~3.28.0",
+ "@opentiny/vue-row": "~3.28.0",
+ "@opentiny/vue-search": "~3.28.0",
+ "@opentiny/vue-select": "~3.28.0",
+ "@opentiny/vue-switch": "~3.28.0",
+ "@opentiny/vue-tab-item": "~3.28.0",
+ "@opentiny/vue-tabs": "~3.28.0",
+ "@opentiny/vue-transfer": "~3.28.0",
+ "@opentiny/vue-tree": "~3.28.0",
"gridstack": "^12.4.2",
"vue": "^3.5.13"
},
@@ -35,15 +91,15 @@
"types": "./dist/index.d.ts",
"require": "./dist/index.js"
},
- "./render-config": {
- "import": "./dist/render-config.js",
- "types": "./dist/render-config.d.ts",
- "require": "./dist/render-config.js"
+ "./meta": {
+ "import": "./dist/meta.js",
+ "types": "./dist/meta.d.ts",
+ "require": "./dist/meta.js"
},
- "./extend-renderer": {
- "import": "./dist/extend-renderer.js",
- "types": "./dist/extend-renderer.d.ts",
- "require": "./dist/extend-renderer.js"
+ "./materials": {
+ "import": "./dist/materials.js",
+ "types": "./dist/materials.d.ts",
+ "require": "./dist/materials.js"
}
}
}
diff --git a/packages/materials/vue-opentiny-vue/src/components/ActionButton.vue b/packages/materials/vue-opentiny-vue/src/components/ActionButton.vue
deleted file mode 100644
index 51599116..00000000
--- a/packages/materials/vue-opentiny-vue/src/components/ActionButton.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
diff --git a/packages/materials/vue-opentiny-vue/src/components/TinyGridWrap.vue b/packages/materials/vue-opentiny-vue/src/components/TinyGridWrap.vue
deleted file mode 100644
index 1c97aa7d..00000000
--- a/packages/materials/vue-opentiny-vue/src/components/TinyGridWrap.vue
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
diff --git a/packages/materials/vue-opentiny-vue/src/components/TinySelectWrap.vue b/packages/materials/vue-opentiny-vue/src/components/TinySelectWrap.vue
deleted file mode 100644
index 18fa7168..00000000
--- a/packages/materials/vue-opentiny-vue/src/components/TinySelectWrap.vue
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
diff --git a/packages/materials/vue-opentiny-vue/src/extend-renderer.ts b/packages/materials/vue-opentiny-vue/src/extend-renderer.ts
deleted file mode 100644
index b681b75d..00000000
--- a/packages/materials/vue-opentiny-vue/src/extend-renderer.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { Component } from 'vue';
-import TinySelectWrap from './components/TinySelectWrap.vue';
-// TODO: to be remove
-// import ActionButton from './components/ActionButton.vue';
-import TinyTabsWrap from './components/TinyTabsWrap.vue';
-// import GridStack from './components/GridStack.vue';
-// import GridStackItem from './components/GridStackItem.vue';
-
-export let extened = false;
-export const extendMapper = (Mapper: any, customComponents: Record) => {
- if (extened) return;
- extened = true;
- Mapper.TinySelect = TinySelectWrap;
- // Mapper.ActionButton = ActionButton;
- Mapper.TinyTabs = TinyTabsWrap;
-
- Object.keys(customComponents).forEach((key) => {
- Mapper[key] = customComponents[key];
- });
- // Mapper.GridStack = GridStack;
- // Mapper.GridStackItem = GridStackItem;
-};
diff --git a/packages/materials/vue-opentiny-vue/src/index.ts b/packages/materials/vue-opentiny-vue/src/index.ts
index e79b1eb0..23468d18 100644
--- a/packages/materials/vue-opentiny-vue/src/index.ts
+++ b/packages/materials/vue-opentiny-vue/src/index.ts
@@ -1,2 +1,2 @@
-export * from './render-config';
-export * from './extend-renderer';
\ No newline at end of file
+export * from './meta';
+export * from './materials';
\ No newline at end of file
diff --git a/packages/materials/vue-opentiny-vue/src/components/GridStack.vue b/packages/materials/vue-opentiny-vue/src/materials/components/GridStack.vue
similarity index 100%
rename from packages/materials/vue-opentiny-vue/src/components/GridStack.vue
rename to packages/materials/vue-opentiny-vue/src/materials/components/GridStack.vue
diff --git a/packages/materials/vue-opentiny-vue/src/components/GridStackItem.vue b/packages/materials/vue-opentiny-vue/src/materials/components/GridStackItem.vue
similarity index 100%
rename from packages/materials/vue-opentiny-vue/src/components/GridStackItem.vue
rename to packages/materials/vue-opentiny-vue/src/materials/components/GridStackItem.vue
diff --git a/packages/materials/vue-opentiny-vue/src/components/TinyTabsWrap.vue b/packages/materials/vue-opentiny-vue/src/materials/components/TinyTabsWrap.vue
similarity index 100%
rename from packages/materials/vue-opentiny-vue/src/components/TinyTabsWrap.vue
rename to packages/materials/vue-opentiny-vue/src/materials/components/TinyTabsWrap.vue
diff --git a/packages/materials/vue-opentiny-vue/src/materials/components/components.ts b/packages/materials/vue-opentiny-vue/src/materials/components/components.ts
new file mode 100644
index 00000000..784ae80e
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/materials/components/components.ts
@@ -0,0 +1,85 @@
+import type { Component } from 'vue';
+import TinyButton from '@opentiny/vue-button';
+import TinyCard from '@opentiny/vue-card';
+import TinyCarousel from '@opentiny/vue-carousel';
+import TinyCarouselItem from '@opentiny/vue-carousel-item';
+import TinyHuichartsBar from '@opentiny/vue-huicharts-bar';
+import TinyHuichartsFunnel from '@opentiny/vue-huicharts-funnel';
+import TinyHuichartsGauge from '@opentiny/vue-huicharts-gauge';
+import TinyHuichartsGraph from '@opentiny/vue-huicharts-graph';
+import TinyHuichartsHistogram from '@opentiny/vue-huicharts-histogram';
+import TinyHuichartsLine from '@opentiny/vue-huicharts-line';
+import TinyHuichartsPie from '@opentiny/vue-huicharts-pie';
+import TinyHuichartsProcess from '@opentiny/vue-huicharts-process';
+import TinyHuichartsRadar from '@opentiny/vue-huicharts-radar';
+import TinyHuichartsRing from '@opentiny/vue-huicharts-ring';
+import TinyHuichartsScatter from '@opentiny/vue-huicharts-scatter';
+import TinyHuichartsWaterfall from '@opentiny/vue-huicharts-waterfall';
+import TinyCheckbox from '@opentiny/vue-checkbox';
+import TinyCheckboxButton from '@opentiny/vue-checkbox-button';
+import TinyCheckboxGroup from '@opentiny/vue-checkbox-group';
+import TinyCol from '@opentiny/vue-col';
+import TinyDatePicker from '@opentiny/vue-date-picker';
+import TinyForm from '@opentiny/vue-form';
+import TinyFormItem from '@opentiny/vue-form-item';
+import TinyGrid from '@opentiny/vue-grid';
+import TinyInput from '@opentiny/vue-input';
+import TinyLayout from '@opentiny/vue-layout';
+import TinyNumeric from '@opentiny/vue-numeric';
+import TinyPager from '@opentiny/vue-pager';
+import TinyRadio from '@opentiny/vue-radio';
+import TinyRadioGroup from '@opentiny/vue-radio-group';
+import TinyRow from '@opentiny/vue-row';
+import TinySearch from '@opentiny/vue-search';
+import TinySwitch from '@opentiny/vue-switch';
+import TinyTabItem from '@opentiny/vue-tab-item';
+import TinyTransfer from '@opentiny/vue-transfer';
+import TinyTree from '@opentiny/vue-tree';
+import TinySelect from '@opentiny/vue-select';
+
+import TinyTabsWrap from './TinyTabsWrap.vue';
+
+export interface IComponents {
+ [key: string]: Component;
+}
+
+export const components: IComponents = {
+ TinyCarouselItem: TinyCarouselItem,
+ TinyCarousel: TinyCarousel,
+ TinyRow: TinyRow,
+ TinyLayout: TinyLayout,
+ TinyForm: TinyForm,
+ TinyFormItem: TinyFormItem,
+ TinyCol: TinyCol,
+ TinyButton: TinyButton,
+ TinyInput: TinyInput,
+ TinyRadio: TinyRadio,
+ TinyRadioGroup: TinyRadioGroup,
+ TinySwitch: TinySwitch,
+ TinySearch: TinySearch,
+ TinyCheckbox: TinyCheckbox,
+ TinyCheckboxButton: TinyCheckboxButton,
+ TinyCheckboxGroup: TinyCheckboxGroup,
+ TinyTabItem: TinyTabItem,
+ TinyGrid: TinyGrid,
+ TinyCard: TinyCard,
+ TinyTree: TinyTree,
+ TinyDatePicker: TinyDatePicker,
+ TinyNumeric: TinyNumeric,
+ TinyPager: TinyPager,
+ TinyTransfer: TinyTransfer,
+ TinyHuichartsLine: TinyHuichartsLine,
+ TinyHuichartsHistogram: TinyHuichartsHistogram,
+ TinyHuichartsBar: TinyHuichartsBar,
+ TinyHuichartsRadar: TinyHuichartsRadar,
+ TinyHuichartsRing: TinyHuichartsRing,
+ TinyHuichartsPie: TinyHuichartsPie,
+ TinyHuichartsFunnel: TinyHuichartsFunnel,
+ TinyHuichartsScatter: TinyHuichartsScatter,
+ TinyHuichartsWaterfall: TinyHuichartsWaterfall,
+ TinyHuichartsGauge: TinyHuichartsGauge,
+ TinyHuichartsGraph: TinyHuichartsGraph,
+ TinyHuichartsProcess: TinyHuichartsProcess,
+ TinyTabs: TinyTabsWrap,
+ TinySelect: TinySelect,
+};
diff --git a/packages/materials/vue-opentiny-vue/src/components/i18n.ts b/packages/materials/vue-opentiny-vue/src/materials/components/i18n.ts
similarity index 100%
rename from packages/materials/vue-opentiny-vue/src/components/i18n.ts
rename to packages/materials/vue-opentiny-vue/src/materials/components/i18n.ts
diff --git a/packages/materials/vue-opentiny-vue/src/materials/components/index.ts b/packages/materials/vue-opentiny-vue/src/materials/components/index.ts
new file mode 100644
index 00000000..07635cbb
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/materials/components/index.ts
@@ -0,0 +1 @@
+export * from './components';
diff --git a/packages/materials/vue-opentiny-vue/src/materials/index.ts b/packages/materials/vue-opentiny-vue/src/materials/index.ts
new file mode 100644
index 00000000..ea409aff
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/materials/index.ts
@@ -0,0 +1 @@
+export * from './materials';
diff --git a/packages/materials/vue-opentiny-vue/src/materials/materials.ts b/packages/materials/vue-opentiny-vue/src/materials/materials.ts
new file mode 100644
index 00000000..ccc4c10d
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/materials/materials.ts
@@ -0,0 +1,29 @@
+import { buildMaterialDefaultValueMap, type IMaterials } from '@opentiny/genui-sdk-core';
+import { materialsMeta, miniMaterialsMeta } from '../meta';
+import { components } from './components';
+
+const baseRequiredCompleteFieldSelectors = [
+ '[componentName=TinyNumeric] > props > controlsPosition',
+ '[componentName=TinyNumeric] > props > modelValue',
+ '[componentName=TinyForm] > props > labelPosition',
+ '[componentName=TinyRadioGroup] > props > options > * > label',
+];
+
+const standardRequiredCompleteFieldSelectors = [
+ ...baseRequiredCompleteFieldSelectors,
+ '[componentName=TinyTabItem] > props > name',
+ '[componentName=TinyTransfer] > props > data',
+ '[componentName^=TinyHuicharts] > props > options > theme',
+];
+
+export const materials: IMaterials = {
+ components,
+ requiredCompleteFieldSelectors: standardRequiredCompleteFieldSelectors,
+ defaultPropsMap: buildMaterialDefaultValueMap(materialsMeta),
+};
+
+export const miniMaterials = {
+ components,
+ requiredCompleteFieldSelectors: baseRequiredCompleteFieldSelectors,
+ defaultPropsMap: buildMaterialDefaultValueMap(miniMaterialsMeta),
+};
diff --git a/packages/materials/vue-opentiny-vue/src/meta/example-schema.ts b/packages/materials/vue-opentiny-vue/src/meta/example-schema.ts
new file mode 100644
index 00000000..d0afc68b
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/example-schema.ts
@@ -0,0 +1,12 @@
+import type { IExample } from '@opentiny/genui-sdk-core';
+import formSchema from './examples/form.json' with { type: 'json' };
+import infoCardSchema from './examples/info.json' with { type: 'json' };
+import gridSchema from './examples/grid.json' with { type: 'json' };
+import tabsSchema from './examples/tabs.json' with { type: 'json' };
+
+export const examples = [
+ { id: 'form', name: '双向绑定的表单', schema: formSchema },
+ { id: 'info', name: '信息展示卡片', schema: infoCardSchema },
+ { id: 'grid', name: '表格卡片', schema: gridSchema },
+ { id: 'tabs', name: 'Tabs卡片', schema: tabsSchema },
+] as IExample[];
diff --git a/packages/materials/vue-opentiny-vue/src/meta/examples/form.json b/packages/materials/vue-opentiny-vue/src/meta/examples/form.json
new file mode 100644
index 00000000..daec8e07
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/examples/form.json
@@ -0,0 +1,166 @@
+{
+ "state": {
+ "formData": {
+ "name": "张三",
+ "sex": "男",
+ "depart": "HR",
+ "protocolStart": "2023-01-01"
+ }
+ },
+ "refs": {
+ "formRef": null
+ },
+ "methods": {
+ "departChange": {
+ "type": "JSFunction",
+ "value": "function departChange(value) { console.log(value) }"
+ }
+ },
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "h3",
+ "children": "更新员工信息"
+ },
+ {
+ "componentName": "TinyForm",
+ "props": {
+ "model": {
+ "type": "JSExpression",
+ "value": "this.state.formData"
+ },
+ "ref": {
+ "type": "JSExpression",
+ "value": "this.refs.formRef"
+ },
+ "labelPosition": "top"
+ },
+ "children": [
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "姓名",
+ "prop": "name",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "TinyInput",
+ "props": {
+ "placeholder": "请输入",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.name"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "性别",
+ "prop": "sex"
+ },
+ "children": [
+ {
+ "componentName": "TinyRadioGroup",
+ "props": {
+ "options": [
+ {
+ "text": "男",
+ "label": "男"
+ },
+ {
+ "text": "女",
+ "label": "女"
+ }
+ ],
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.sex"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "部门",
+ "prop": "depart",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "TinySelect",
+ "props": {
+ "placeholder": "请选择",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.depart"
+ },
+ "options": [
+ {
+ "value": "HR",
+ "label": "人事部"
+ },
+ {
+ "value": "other",
+ "label": "其他部门"
+ }
+ ],
+ "onChange": {
+ "type": "JSExpression",
+ "value": "this.departChange"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "入职日期",
+ "prop": "protocolStart"
+ },
+ "children": [
+ {
+ "componentName": "TinyDatePicker",
+ "props": {
+ "placeholder": "请输入",
+ "disabled": true,
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.formData.protocolStart"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": ""
+ },
+ "children": [
+ {
+ "componentName": "TinyButton",
+ "props": {
+ "text": "确认",
+ "onClick": {
+ "type": "JSFunction",
+ "value": "function() { this.refs.formRef.validate().then(res => { console.log(\"校验通过\", res) }).catch((err) => { console.log(\"校验失败, 失败只做提示,不继续会话\", err) }) }"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-opentiny-vue/src/meta/examples/grid.json b/packages/materials/vue-opentiny-vue/src/meta/examples/grid.json
new file mode 100644
index 00000000..d7d0f358
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/examples/grid.json
@@ -0,0 +1,91 @@
+{
+ "componentName": "Page",
+ "css": ".page-base-style {padding: 24px;background: #FFFFFF;}.block-base-style {margin: 16px;}.component-base-style {margin: 8px;}",
+ "props": {
+ "className": "page-base-style"
+ },
+ "lifeCycles": {},
+ "children": [
+ {
+ "componentName": "TinyGrid",
+ "props": {
+ "columns": [
+ {
+ "type": "index",
+ "width": 60
+ },
+ {
+ "field": "name",
+ "title": "姓名"
+ },
+ {
+ "field": "id",
+ "title": "工号"
+ },
+ {
+ "field": "sex",
+ "title": "性别"
+ },
+ {
+ "field": "department",
+ "title": "部门"
+ },
+ {
+ "field": "protocolStart",
+ "title": "入职日期"
+ },
+ {
+ "field": "email",
+ "title": "邮箱"
+ },
+ {
+ "title": "操作",
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "div",
+ "id": "23324161",
+ "children": [
+ {
+ "componentName": "TinyButton",
+ "props": {
+ "className": "component-base-style",
+ "text": {
+ "type": "JSExpression",
+ "value": "`编辑${row.name}`"
+ }
+ },
+ "children": [],
+ "id": "24392624"
+ }
+ ]
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ }
+ ],
+ "data": [
+ {
+ "name": "李四",
+ "id": "2",
+ "sex": "女",
+ "department": "技术部",
+ "protocolStart": "2019-05-15",
+ "email": "lisi@test.com"
+ }
+ ],
+ "className": "component-base-style"
+ }
+ }
+ ],
+ "dataSource": {
+ "list": []
+ },
+ "id": "body"
+}
diff --git a/packages/materials/vue-opentiny-vue/src/meta/examples/info.json b/packages/materials/vue-opentiny-vue/src/meta/examples/info.json
new file mode 100644
index 00000000..0b7b5ff7
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/examples/info.json
@@ -0,0 +1,96 @@
+{
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "style": "font-size: 14px;font-weight: bold;line-height:2;margin-bottom:20px;display:block;",
+ "text": "员工信息详情"
+ }
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "className": "component-base-style",
+ "style": "width: 374px; background: #f5f5f5;border-radius: 12px;line-height:2;font-size:14px;padding: 20px 0;"
+ },
+ "children": [
+ {
+ "componentName": "TinyLayout",
+ "props": {
+ "className": "component-base-style"
+ },
+ "children": [
+ {
+ "componentName": "TinyRow",
+ "children": [
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 3
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "姓名"
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 9
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "张三"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TinyRow",
+ "children": [
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 3
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "电话"
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 9
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "18856254558"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "id": "body"
+}
diff --git a/packages/materials/vue-opentiny-vue/src/meta/examples/tabs.json b/packages/materials/vue-opentiny-vue/src/meta/examples/tabs.json
new file mode 100644
index 00000000..793dc5fc
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/examples/tabs.json
@@ -0,0 +1,83 @@
+{
+ "state": {
+ "activeTab": "basic"
+ },
+ "methods": {},
+ "componentName": "Page",
+ "children": [
+ {
+ "componentName": "h3",
+ "props": {},
+ "children": "订单详情"
+ },
+ {
+ "componentName": "TinyTabs",
+ "props": {
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.activeTab"
+ }
+ },
+ "children": [
+ {
+ "componentName": "TinyTabItem",
+ "props": {
+ "title": "基本信息",
+ "name": "basic"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "订单号:ORD-20240301"
+ }
+ },
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "下单时间:2024-03-01 10:30"
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyTabItem",
+ "props": {
+ "title": "物流信息",
+ "name": "logistics"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "承运商:顺丰速运"
+ }
+ },
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "运单号:SF1234567890"
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyTabItem",
+ "props": {
+ "title": "售后",
+ "name": "service"
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": "暂无售后记录"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/materials/vue-opentiny-vue/src/meta/index.ts b/packages/materials/vue-opentiny-vue/src/meta/index.ts
new file mode 100644
index 00000000..c9942f46
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/index.ts
@@ -0,0 +1 @@
+export * from './meta';
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/builtin.json b/packages/materials/vue-opentiny-vue/src/meta/materials/builtin.json
similarity index 91%
rename from packages/materials/vue-opentiny-vue/src/render-config/builtin.json
rename to packages/materials/vue-opentiny-vue/src/meta/materials/builtin.json
index e878aa03..8f732d65 100644
--- a/packages/materials/vue-opentiny-vue/src/render-config/builtin.json
+++ b/packages/materials/vue-opentiny-vue/src/meta/materials/builtin.json
@@ -2,71 +2,6 @@
"data": {
"materials": {
"components": [
- {
- "icon": "Box",
- "name": {
- "zh_CN": "Box"
- },
- "component": "div",
- "schema": {
- "slots": {
- },
- "properties": [
- {
- "label": {
- "zh_CN": "基础信息"
- },
- "description": {
- "zh_CN": "基础信息"
- },
- "collapse": {
- "number": 6,
- "text": {
- "zh_CN": "显示更多"
- }
- },
- "content": [
- ]
- }
- ],
- "events": {
- "onClick": {
- "label": {
- "zh_CN": "点击事件"
- },
- "description": {
- "zh_CN": "点击时触发的回调函数"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- ],
- "returns": {
- }
- },
- "defaultValue": ""
- }
- },
- "shortcuts": {
- "properties": [
- ]
- },
- "contentMenu": {
- "actions": [
- ]
- }
- },
- "configure": {
- "loop": true,
- "isContainer": true,
- "nestingRule": {
- "childWhitelist": [
- ],
- "descendantBlacklist": [
- ]
- }
- }
- },
{
"icon": "slot",
"name": {
@@ -107,7 +42,6 @@
{
"property": "params",
"type": "string",
- "defaultValue": "",
"label": {
"text": {
"zh_CN": "作用域参数"
@@ -264,7 +198,6 @@
{
"property": "condition",
"type": "boolean",
- "defaultValue": true,
"label": {
"text": {
"zh_CN": "是否渲染"
@@ -282,7 +215,6 @@
{
"property": "style",
"type": "string",
- "defaultValue": "",
"label": {
"text": {
"zh_CN": "样式"
@@ -300,7 +232,6 @@
{
"property": "dataSource",
"type": "string",
- "defaultValue": "",
"bindState": false,
"label": {
"text": {
@@ -359,7 +290,6 @@
{
"property": "text",
"type": "string",
- "defaultValue": "您好!欢迎使用生成式UI。它将重塑大模型交互方式,打造极致顺滑的智能体验。",
"label": {
"text": {
"zh_CN": "文本内容"
@@ -393,8 +323,7 @@
],
"returns": {
}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
@@ -437,7 +366,6 @@
{
"property": "name",
"type": "string",
- "defaultValue": "IconDel",
"bindState": true,
"label": {
"text": {
@@ -470,8 +398,7 @@
],
"returns": {
}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
@@ -514,7 +441,6 @@
{
"property": "src",
"type": "string",
- "defaultValue": "",
"bindState": true,
"label": {
"text": {
@@ -547,8 +473,7 @@
],
"returns": {
}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/bundle.json b/packages/materials/vue-opentiny-vue/src/meta/materials/bundle.json
similarity index 74%
rename from packages/materials/vue-opentiny-vue/src/render-config/bundle.json
rename to packages/materials/vue-opentiny-vue/src/meta/materials/bundle.json
index 3db33b8c..69e66957 100644
--- a/packages/materials/vue-opentiny-vue/src/render-config/bundle.json
+++ b/packages/materials/vue-opentiny-vue/src/meta/materials/bundle.json
@@ -3,3165 +3,6 @@
"framework": "Vue",
"materials": {
"components": [
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "输入框"
- },
- "component": "ElInput",
- "icon": "input",
- "description": "通过鼠标或键盘输入字符",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElInput",
- "destructuring": true
- },
- "group": "表单组件",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["type", "size"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "modelValue",
- "label": {
- "text": {
- "zh_CN": "绑定值"
- }
- },
- "description": {
- "zh_CN": "绑定值"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "尺寸"
- }
- },
- "description": {
- "zh_CN": "尺寸"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "default",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "default",
- "value": "default"
- },
- {
- "label": "small",
- "value": "small"
- }
- ]
- }
- }
- },
- {
- "property": "type",
- "label": {
- "text": {
- "zh_CN": "类型"
- }
- },
- "description": {
- "zh_CN": "类型"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "placeholder",
- "label": {
- "text": {
- "zh_CN": "占位文本"
- }
- },
- "description": {
- "zh_CN": "输入框占位文本"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "I18nConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "maxlength",
- "label": {
- "text": {
- "zh_CN": "最大长度"
- }
- },
- "description": {
- "zh_CN": "最大输入长度"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "number",
- "widget": {
- "component": "NumberConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "disabled",
- "label": {
- "text": {
- "zh_CN": "是否禁用"
- }
- },
- "description": {
- "zh_CN": "是否禁用"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {
- "onUpdate:modelValue": {
- "label": {
- "zh_CN": "双向绑定值改变时触发"
- },
- "description": {
- "zh_CN": "双向绑定值改变时触发"
- }
- },
- "onBlur": {
- "label": {
- "zh_CN": "输入框失去焦点时触发"
- },
- "description": {
- "zh_CN": "输入框失去焦点时触发"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "event",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "原生 event"
- }
- }
- ],
- "returns": {}
- },
- "defaultValue": ""
- }
- },
- "slots": {
- "prefix": {
- "label": {
- "zh_CN": "头部内容"
- },
- "description": {
- "zh_CN": "输入框头部内容,只对非 type='textarea' 有效"
- }
- },
- "suffix": {
- "label": {
- "zh_CN": "尾部内容"
- },
- "description": {
- "zh_CN": "输入框尾部内容,只对非 type='textarea' 有效"
- }
- },
- "prepend": {
- "label": {
- "zh_CN": "前置内容"
- },
- "description": {
- "zh_CN": "输入框前置内容,只对非 type='textarea' 有效"
- }
- },
- "append": {
- "label": {
- "zh_CN": "后置内容"
- },
- "description": {
- "zh_CN": "输入框后置内容,只对非 type='textarea' 有效"
- }
- }
- }
- }
- },
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "日期选择器"
- },
- "component": "ElDatePicker",
- "icon": "datepick",
- "description": "日期选择器",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElDatePicker",
- "destructuring": true
- },
- "group": "表单组件",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["type", "size"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "modelValue",
- "label": {
- "text": {
- "zh_CN": "绑定值"
- }
- },
- "description": {
- "zh_CN": "绑定值"
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "readonly",
- "label": {
- "text": {
- "zh_CN": "只读"
- }
- },
- "description": {
- "zh_CN": "是否只读"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "defaultValue": false,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "disabled",
- "label": {
- "text": {
- "zh_CN": "禁用"
- }
- },
- "description": {
- "zh_CN": "是否禁用"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "defaultValue": false,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "尺寸"
- }
- },
- "description": {
- "zh_CN": "输入框尺寸"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "allowClear": true,
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "default",
- "value": "default"
- },
- {
- "label": "small",
- "value": "small"
- }
- ]
- }
- }
- },
- {
- "property": "editable",
- "label": {
- "text": {
- "zh_CN": "是否可编辑"
- }
- },
- "description": {
- "zh_CN": "文本框是否可编辑"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "defaultValue": true,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "clearable",
- "label": {
- "text": {
- "zh_CN": "是否可清除"
- }
- },
- "description": {
- "zh_CN": "是否显示清楚按钮"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "defaultValue": true,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "placeholder",
- "label": {
- "text": {
- "zh_CN": "占位文本"
- }
- },
- "description": {
- "zh_CN": "非范围选择时的占位内容"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": "",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "start-placeholder",
- "label": {
- "text": {
- "zh_CN": "起始占位文本"
- }
- },
- "description": {
- "zh_CN": "范围选择时开始日期的占位内容"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": "",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "end-placeholder",
- "label": {
- "text": {
- "zh_CN": "结束占位文本"
- }
- },
- "description": {
- "zh_CN": "范围选择时结束日期的占位内容"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": "",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "type",
- "label": {
- "text": {
- "zh_CN": "类型"
- }
- },
- "description": {
- "zh_CN": "显示类型"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": "date",
- "type": "string",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "year",
- "value": "year"
- },
- {
- "label": "years",
- "value": "years"
- },
- {
- "label": "month",
- "value": "month"
- },
- {
- "label": "months",
- "value": "months"
- },
- {
- "label": "date",
- "value": "date"
- },
- {
- "label": "dates",
- "value": "dates"
- },
- {
- "label": "datetime",
- "value": "datetime"
- },
- {
- "label": "week",
- "value": "week"
- },
- {
- "label": "datetimerange",
- "value": "datetimerange"
- },
- {
- "label": "daterange",
- "value": "daterange"
- },
- {
- "label": "monthrange",
- "value": "monthrange"
- },
- {
- "label": "yearrange",
- "value": "yearrange"
- }
- ]
- }
- },
- "device": []
- },
- {
- "property": "popper-class",
- "label": {
- "text": {
- "zh_CN": "下拉框类名"
- }
- },
- "description": {
- "zh_CN": "DatePicker 下拉框的类名"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": "",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {
- "onUpdate:modelValue": {
- "label": {
- "zh_CN": "双向绑定值改变时触发"
- },
- "description": {
- "zh_CN": "双向绑定值改变时触发"
- }
- },
- "onChange": {
- "label": {
- "zh_CN": "用户确认选定的值时触发"
- },
- "description": {
- "zh_CN": "用户确认选定的值时触发"
- },
- "type": "event",
- "defaultValue": ""
- },
- "onBlur": {
- "label": {
- "zh_CN": "在组件 Input 失去焦点时触发"
- },
- "description": {
- "zh_CN": "在组件 Input 失去焦点时触发"
- },
- "type": "event",
- "defaultValue": ""
- },
- "onFocus": {
- "label": {
- "zh_CN": "在组件 Input 获得焦点时触发"
- },
- "description": {
- "zh_CN": "在组件 Input 获得焦点时触发"
- },
- "type": "event",
- "defaultValue": ""
- },
- "onCalendarChange": {
- "label": {
- "zh_CN": "在日历所选日期更改时触发"
- },
- "description": {
- "zh_CN": "在日历所选日期更改时触发"
- },
- "type": "event",
- "defaultValue": ""
- },
- "onPanelChange": {
- "label": {
- "zh_CN": "当日期面板改变时触发。"
- },
- "description": {
- "zh_CN": "当日期面板改变时触发。"
- },
- "type": "event",
- "defaultValue": ""
- },
- "onVisibleChange": {
- "label": {
- "zh_CN": "当 DatePicker 的下拉列表出现/消失时触发"
- },
- "description": {
- "zh_CN": "当 DatePicker 的下拉列表出现/消失时触发"
- },
- "type": "event",
- "defaultValue": ""
- }
- },
- "slots": {
- "default": {
- "label": {
- "zh_CN": "自定义单元格内容"
- },
- "description": {
- "zh_CN": "自定义单元格内容"
- }
- },
- "range-separator": {
- "label": {
- "zh_CN": "自定义范围分割符内容"
- },
- "description": {
- "zh_CN": "自定义范围分割符内容"
- }
- }
- }
- }
- },
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "按钮"
- },
- "component": "ElButton",
- "icon": "button",
- "description": "常用的操作按钮",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElButton",
- "destructuring": true
- },
- "group": "基础组件",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": true,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["type", "size"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "尺寸"
- }
- },
- "description": {
- "zh_CN": "尺寸"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "default",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "default",
- "value": "default"
- },
- {
- "label": "small",
- "value": "small"
- }
- ]
- }
- }
- },
- {
- "property": "type",
- "label": {
- "text": {
- "zh_CN": "类型"
- }
- },
- "description": {
- "zh_CN": "类型"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "plain",
- "label": {
- "text": {
- "zh_CN": "朴素按钮"
- }
- },
- "description": {
- "zh_CN": "是否为朴素按钮"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "text",
- "label": {
- "text": {
- "zh_CN": "文字按钮"
- }
- },
- "description": {
- "zh_CN": "是否为文字按钮"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "bg",
- "label": {
- "text": {
- "zh_CN": "背景颜色"
- }
- },
- "description": {
- "zh_CN": "是否显示文字按钮背景颜色"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "link",
- "label": {
- "text": {
- "zh_CN": "链接按钮"
- }
- },
- "description": {
- "zh_CN": "是否为链接按钮"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "round",
- "label": {
- "text": {
- "zh_CN": "圆角按钮"
- }
- },
- "description": {
- "zh_CN": "是否为圆角按钮"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "circle",
- "label": {
- "text": {
- "zh_CN": "圆形按钮"
- }
- },
- "description": {
- "zh_CN": "是否为圆形按钮"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "加载中状态"
- }
- },
- "description": {
- "zh_CN": "是否为加载中状态"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "disabled",
- "label": {
- "text": {
- "zh_CN": "禁用"
- }
- },
- "description": {
- "zh_CN": "是否禁用"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {},
- "slots": {
- "default": {
- "label": {
- "zh_CN": "default"
- },
- "description": {
- "zh_CN": "自定义默认内容"
- }
- },
- "loading": {
- "label": {
- "zh_CN": "loading"
- },
- "description": {
- "zh_CN": "自定义加载中组件"
- }
- }
- }
- }
- },
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "表单"
- },
- "component": "ElForm",
- "icon": "form",
- "description": "表单包含 输入框, 单选框, 下拉选择, 多选框 等用户输入的组件。 使用表单,您可以收集、验证和提交数据。",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElForm",
- "destructuring": true
- },
- "group": "表单组件",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": true,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": ["ElFormItem"],
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["inline", "label-width"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "model",
- "label": {
- "text": {
- "zh_CN": "数据对象"
- }
- },
- "description": {
- "zh_CN": "表单数据对象"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "rules",
- "label": {
- "text": {
- "zh_CN": "验证规则"
- }
- },
- "description": {
- "zh_CN": "表单验证规则"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "inline",
- "label": {
- "text": {
- "zh_CN": "行内模式"
- }
- },
- "description": {
- "zh_CN": "行内表单模式"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "label-position",
- "label": {
- "text": {
- "zh_CN": "标签位置"
- }
- },
- "description": {
- "zh_CN": "表单域标签的位置, 当设置为 left 或 right 时,则也需要设置标签宽度属性"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "right",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "left",
- "value": "left"
- },
- {
- "label": "right",
- "value": "right"
- },
- {
- "label": "top",
- "value": "top"
- }
- ]
- }
- }
- },
- {
- "property": "label-width",
- "label": {
- "text": {
- "zh_CN": "标签宽度"
- }
- },
- "description": {
- "zh_CN": "标签的长度,例如 '50px'。 作为 Form 直接子元素的 form-item 会继承该值。 可以使用 auto。"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "label-suffix",
- "label": {
- "text": {
- "zh_CN": "标签后缀"
- }
- },
- "description": {
- "zh_CN": "表单域标签的后缀"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "hide-required-asterisk",
- "label": {
- "text": {
- "zh_CN": "隐藏必填星号"
- }
- },
- "description": {
- "zh_CN": "是否隐藏必填字段标签旁边的红色星号"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "require-asterisk-position",
- "label": {
- "text": {
- "zh_CN": "星号位置"
- }
- },
- "description": {
- "zh_CN": "星号的位置"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "left",
- "widget": {
- "component": "ButtonGroupConfigurator",
- "props": {
- "options": [
- {
- "label": "left",
- "value": "left"
- },
- {
- "label": "right",
- "value": "right"
- }
- ]
- }
- }
- },
- {
- "property": "show-message",
- "label": {
- "text": {
- "zh_CN": "显示校验信息"
- }
- },
- "description": {
- "zh_CN": "是否显示校验错误信息"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": true,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "inline-message",
- "label": {
- "text": {
- "zh_CN": "行内显示校验信息"
- }
- },
- "description": {
- "zh_CN": "是否以行内形式展示校验信息"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "status-icon",
- "label": {
- "text": {
- "zh_CN": "显示校验结果图标"
- }
- },
- "description": {
- "zh_CN": "是否在输入框中显示校验结果反馈图标"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "validate-on-rule-change",
- "label": {
- "text": {
- "zh_CN": "触发验证"
- }
- },
- "description": {
- "zh_CN": "是否在 rules 属性改变后立即触发一次验证"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": true,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "尺寸"
- }
- },
- "description": {
- "zh_CN": "用于控制该表单内组件的尺寸"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "default",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "default",
- "value": "default"
- },
- {
- "label": "small",
- "value": "small"
- }
- ]
- }
- }
- },
- {
- "property": "disabled",
- "label": {
- "text": {
- "zh_CN": "禁用"
- }
- },
- "description": {
- "zh_CN": "是否禁用该表单内的所有组件。 如果设置为 true, 它将覆盖内部组件的 disabled 属性"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "scroll-to-error",
- "label": {
- "text": {
- "zh_CN": "滚动到错误项"
- }
- },
- "description": {
- "zh_CN": "当校验失败时,滚动到第一个错误表单项"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "device": []
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {
- "onValidate": {
- "label": {
- "zh_CN": "任一表单项被校验后触发"
- },
- "description": {
- "zh_CN": "任一表单项被校验后触发"
- },
- "type": "event",
- "functionInfo": {
- "params": [],
- "returns": {}
- },
- "defaultValue": ""
- }
- },
- "slots": {}
- }
- },
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "表单子项"
- },
- "component": "ElFormItem",
- "icon": "formItem",
- "description": "表单包含 输入框, 单选框, 下拉选择, 多选框 等用户输入的组件。 使用表单,您可以收集、验证和提交数据。",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElFormItem",
- "destructuring": true
- },
- "group": "表单组件",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": true,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["inline", "label-width"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "prop",
- "label": {
- "text": {
- "zh_CN": "键名"
- }
- },
- "description": {
- "zh_CN": "model 的键名。 它可以是一个属性的值(如 a.b.0 或 [a', 'b', '0'])。 在定义了 validate、resetFields 的方法时,该属性是必填的"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "label",
- "label": {
- "text": {
- "zh_CN": "标签文本"
- }
- },
- "description": {
- "zh_CN": "标签文本"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "label-width",
- "label": {
- "text": {
- "zh_CN": "标签宽度"
- }
- },
- "description": {
- "zh_CN": "标签宽度,例如 '50px'。 可以使用 auto"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "required",
- "label": {
- "text": {
- "zh_CN": "必填项"
- }
- },
- "description": {
- "zh_CN": "是否为必填项,如不设置,则会根据校验规则确认"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "rules",
- "label": {
- "text": {
- "zh_CN": "验证规则"
- }
- },
- "description": {
- "zh_CN": "表单验证规则, 更多内容可以参考async-validator"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "error",
- "label": {
- "text": {
- "zh_CN": "错误信息"
- }
- },
- "description": {
- "zh_CN": "表单域验证错误时的提示信息。设置该值会导致表单验证状态变为 error,并显示该错误信息"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "show-message",
- "label": {
- "text": {
- "zh_CN": "显示错误信息"
- }
- },
- "description": {
- "zh_CN": "是否显示校验错误信息"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "inline-message",
- "label": {
- "text": {
- "zh_CN": "行内显示错误信息"
- }
- },
- "description": {
- "zh_CN": "是否在行内显示校验信息"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "尺寸"
- }
- },
- "description": {
- "zh_CN": "用于控制该表单内组件的尺寸"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "default",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "default",
- "value": "default"
- },
- {
- "label": "small",
- "value": "small"
- }
- ]
- }
- }
- },
- {
- "property": "for",
- "label": {
- "text": {
- "zh_CN": "for"
- }
- },
- "description": {
- "zh_CN": "和原生标签相同能力"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "validate-status",
- "label": {
- "text": {
- "zh_CN": "校验状态"
- }
- },
- "description": {
- "zh_CN": "formItem 校验的状态"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "error",
- "value": "error"
- },
- {
- "label": "validating",
- "value": "validating"
- },
- {
- "label": "success",
- "value": "success"
- }
- ]
- }
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {},
- "slots": {
- "label": {
- "label": {
- "zh_CN": "label"
- },
- "description": {
- "zh_CN": "标签位置显示的内容"
- }
- },
- "error": {
- "label": {
- "zh_CN": "error"
- },
- "description": {
- "zh_CN": "验证错误信息的显示内容"
- }
- }
- }
- }
- },
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "表单"
- },
- "component": "ElTable",
- "icon": "table",
- "description": "用于展示多条结构类似的数据, 可对数据进行排序、筛选、对比或其他自定义操作",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElTable",
- "destructuring": true
- },
- "group": "数据展示",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": ["ElTableColumn"],
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["inline", "label-width"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "数据"
- }
- },
- "description": {
- "zh_CN": "显示的数据"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "columns",
- "label": {
- "text": {
- "zh_CN": "表格列配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "properties": [
- {
- "label": {
- "zh_CN": "默认分组"
- },
- "content": [
- {
- "property": "type",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "type"
- }
- },
- "description": {
- "text": {
- "zh_CN": "对应列的类型。 如果设置了selection则显示多选框; 如果设置了 index 则显示该行的索引(从 1 开始计算); 如果设置了 expand 则显示为一个可展开的按钮"
- }
- },
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "selection",
- "value": "selection"
- },
- {
- "label": "index",
- "value": "index"
- },
- {
- "label": "expand",
- "value": "expand"
- }
- ]
- }
- }
- },
- {
- "property": "index",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "index"
- }
- },
- "description": {
- "text": {
- "zh_CN": "如果设置了 type=index,可以通过传递 index 属性来自定义索引"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {}
- }
- },
- {
- "property": "label",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "label"
- }
- },
- "description": {
- "text": {
- "zh_CN": "显示的标题"
- }
- },
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "column-key",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "column-key"
- }
- },
- "description": {
- "text": {
- "zh_CN": "column 的 key, column 的 key, 如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件"
- }
- },
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "prop",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "prop"
- }
- },
- "description": {
- "text": {
- "zh_CN": "字段名称 对应列内容的字段名, 也可以使用 property属性"
- }
- },
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "width",
- "type": "number",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "width"
- }
- },
- "description": {
- "text": {
- "zh_CN": "对应列的宽度"
- }
- },
- "widget": {
- "component": "NumberConfigurator",
- "props": {}
- }
- },
- {
- "property": "min-width",
- "type": "number",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "min-width"
- }
- },
- "description": {
- "text": {
- "zh_CN": "对应列的最小宽度, 对应列的最小宽度, 与 width 的区别是 width 是固定的,min-width 会把剩余宽度按比例分配给设置了 min-width 的列"
- }
- },
- "widget": {
- "component": "NumberConfigurator",
- "props": {}
- }
- },
- {
- "property": "fixed",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "fixed"
- }
- },
- "description": {
- "text": {
- "zh_CN": "列是否固定在左侧或者右侧。 true 表示固定在左侧"
- }
- },
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "left",
- "value": "left"
- },
- {
- "label": "right",
- "value": "right"
- }
- ]
- }
- }
- },
- {
- "property": "sortable",
- "type": "boolean",
- "labelPosition": "left",
- "label": {
- "text": {
- "zh_CN": "sortable"
- }
- },
- "description": {
- "text": {
- "zh_CN": "对应列是否可以排序"
- }
- },
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "sort-method",
- "type": "function",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "sort-method"
- }
- },
- "description": {
- "text": {
- "zh_CN": "指定数据按照哪个属性进行排序,仅当sortable设置为true的时候有效。 应该如同 Array.sort 那样返回一个 Number"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {}
- }
- },
- {
- "property": "sort-by",
- "type": "array",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "sort-by"
- }
- },
- "description": {
- "text": {
- "zh_CN": "指定数据按照哪个属性进行排序,仅当 sortable 设置为 true 且没有设置 sort-method 的时候有效。 如果 sort-by 为数组,则先按照第 1 个属性排序,如果第 1 个相等,再按照第 2 个排序,以此类推"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "sort-orders",
- "type": "array",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "sort-orders"
- }
- },
- "description": {
- "text": {
- "zh_CN": "数据在排序时所使用排序策略的轮转顺序,仅当 sortable 为 true 时有效。 需传入一个数组,随着用户点击表头,该列依次按照数组中元素的顺序进行排序"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "resizable",
- "type": "boolean",
- "labelPosition": "left",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "resizable"
- }
- },
- "description": {
- "text": {
- "zh_CN": "对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)"
- }
- },
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "formatter",
- "type": "function",
- "labelPosition": "top",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "formatter"
- }
- },
- "description": {
- "text": {
- "zh_CN": "用来格式化内容"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "dataType": "JSFunction"
- }
- }
- },
- {
- "property": "show-overflow-tooltip",
- "type": "boolean",
- "labelPosition": "left",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "show-overflow-tooltip"
- }
- },
- "description": {
- "text": {
- "zh_CN": "当内容过长被隐藏时显示 tooltip"
- }
- },
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "align",
- "type": "string",
- "labelPosition": "top",
- "defaultValue": "left",
- "label": {
- "text": {
- "zh_CN": "align"
- }
- },
- "description": {
- "text": {
- "zh_CN": "对齐方式"
- }
- },
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "left",
- "value": "left"
- },
- {
- "label": "center",
- "value": "center"
- },
- {
- "label": "right",
- "value": "right"
- }
- ]
- }
- }
- },
- {
- "property": "header-align",
- "type": "string",
- "labelPosition": "top",
- "defaultValue": "left",
- "label": {
- "text": {
- "zh_CN": "header-align"
- }
- },
- "description": {
- "text": {
- "zh_CN": "表头对齐方式, 若不设置该项,则使用表格的对齐方式"
- }
- },
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "left",
- "value": "left"
- },
- {
- "label": "center",
- "value": "center"
- },
- {
- "label": "right",
- "value": "right"
- }
- ]
- }
- }
- },
- {
- "property": "class-name",
- "type": "string",
- "labelPosition": "top",
- "defaultValue": "left",
- "label": {
- "text": {
- "zh_CN": "class-name"
- }
- },
- "description": {
- "text": {
- "zh_CN": "列的 className"
- }
- },
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "label-class-name",
- "type": "string",
- "labelPosition": "top",
- "defaultValue": "left",
- "label": {
- "text": {
- "zh_CN": "label-class-name"
- }
- },
- "description": {
- "text": {
- "zh_CN": "当前列标题的自定义类名"
- }
- },
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "selectable",
- "type": "function",
- "labelPosition": "top",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "selectable"
- }
- },
- "description": {
- "text": {
- "zh_CN": "仅对 type=selection 的列有效,类型为 Function,Function 的返回值用来决定这一行的 CheckBox 是否可以勾选"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {}
- }
- },
- {
- "property": "reserve-selection",
- "type": "boolean",
- "labelPosition": "left",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "reserve-selection"
- }
- },
- "description": {
- "text": {
- "zh_CN": "数据刷新后是否保留选项,仅对 type=selection 的列有效, 请注意, 需指定 row-key 来让这个功能生效。"
- }
- },
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "filters",
- "type": "array",
- "labelPosition": "top",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "filters"
- }
- },
- "description": {
- "text": {
- "zh_CN": "数据刷新后是否保留选项,仅对 type=selection 的列有效, 请注意, 需指定 row-key 来让这个功能生效。"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- },
- {
- "property": "filter-placement",
- "type": "string",
- "labelPosition": "top",
- "label": {
- "text": {
- "zh_CN": "filter-placement"
- }
- },
- "description": {
- "text": {
- "zh_CN": "过滤弹出框的定位"
- }
- },
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- }
- },
- {
- "property": "filter-multiple",
- "type": "string",
- "labelPosition": "left",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "filter-multiple"
- }
- },
- "description": {
- "text": {
- "zh_CN": "数据过滤的选项是否多选"
- }
- },
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "filter-method",
- "type": "function",
- "labelPosition": "top",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "filter-method"
- }
- },
- "description": {
- "text": {
- "zh_CN": "数据过滤使用的方法, 如果是多选的筛选项,对每一条数据会执行多次,任意一次返回 true 就会显示"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {}
- }
- },
- {
- "property": "filtered-value",
- "type": "array",
- "labelPosition": "top",
- "defaultValue": true,
- "label": {
- "text": {
- "zh_CN": "filtered-value"
- }
- },
- "description": {
- "text": {
- "zh_CN": "选中的数据过滤项,如果需要自定义表头过滤的渲染方式,可能会需要此属性"
- }
- },
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- "language": "json"
- }
- }
- }
- ]
- }
- ],
- "widget": {
- "component": "TableColumnsConfigurator",
- "props": {
- "type": "object",
- "textField": "label",
- "language": "json",
- "buttonText": "编辑列配置",
- "title": "编辑列配置",
- "expand": true
- }
- },
- "description": {
- "zh_CN": "表格列的配置信息"
- },
- "labelPosition": "top"
- },
- {
- "property": "max-height",
- "label": {
- "text": {
- "zh_CN": "最大高度"
- }
- },
- "description": {
- "zh_CN": "Table 的最大高度。"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "number",
- "widget": {
- "component": "NumberConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "height",
- "label": {
- "text": {
- "zh_CN": "表格高度"
- }
- },
- "description": {
- "zh_CN": "Table 的高度, 默认为自动高度。 这个高度会设置为 Table 的 style.height 的值,Table 的高度会受控于外部样式。"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "stripe",
- "label": {
- "text": {
- "zh_CN": "斑马纹"
- }
- },
- "description": {
- "zh_CN": "是否为斑马纹 table"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "border",
- "label": {
- "text": {
- "zh_CN": "纵向边框"
- }
- },
- "description": {
- "zh_CN": "是否带有纵向边框"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "表格尺寸"
- }
- },
- "description": {
- "zh_CN": "Table 的尺寸"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "type": "string",
- "defaultValue": "default",
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "default",
- "value": "default"
- },
- {
- "label": "small",
- "value": "small"
- }
- ]
- }
- }
- },
- {
- "property": "fit",
- "label": {
- "text": {
- "zh_CN": "列宽自撑开"
- }
- },
- "description": {
- "zh_CN": "列的宽度是否自撑开"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": true,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "show-header",
- "label": {
- "text": {
- "zh_CN": "显示表头"
- }
- },
- "description": {
- "zh_CN": "是否显示表头"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": true,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "highlight-current-row",
- "label": {
- "text": {
- "zh_CN": "高亮当前行"
- }
- },
- "description": {
- "zh_CN": "是否要高亮当前行"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "current-row-key",
- "label": {
- "text": {
- "zh_CN": "当前行的 key"
- }
- },
- "description": {
- "zh_CN": "当前行的 key,只写属性"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "type": "string",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "row-class-name",
- "label": {
- "text": {
- "zh_CN": "行的类名"
- }
- },
- "description": {
- "zh_CN": "行的 className"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "row-key",
- "label": {
- "text": {
- "zh_CN": "行数据的 Key"
- }
- },
- "description": {
- "zh_CN": "行数据的 Key,用来优化 Table 的渲染; 在使用reserve-selection功能与显示树形数据时,该属性是必填的。 类型为 String 时,支持多层访问:user.info.id,但不支持 user.info[0].id,此种情况请使用 Function"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "widget": {
- "component": "CodeConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "empty-text",
- "label": {
- "text": {
- "zh_CN": "空数据文本"
- }
- },
- "description": {
- "zh_CN": "空数据时显示的文本内容"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "device": []
- },
- {
- "property": "table-layout",
- "label": {
- "text": {
- "zh_CN": "表格布局方式"
- }
- },
- "description": {
- "zh_CN": "设置表格单元、行和列的布局方式"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "top",
- "defaultValue": "fixed",
- "widget": {
- "component": "InputConfigurator",
- "props": {
- "options": [
- {
- "label": "fixed",
- "value": "fixed"
- },
- {
- "label": "auto",
- "value": "auto"
- }
- ]
- }
- },
- "device": []
- },
- {
- "property": "scrollbar-always-on",
- "label": {
- "text": {
- "zh_CN": "显示滚动条"
- }
- },
- "description": {
- "zh_CN": "总是显示滚动条"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- },
- {
- "property": "flexible",
- "label": {
- "text": {
- "zh_CN": "主轴最小尺寸"
- }
- },
- "description": {
- "zh_CN": "确保主轴的最小尺寸,以便不超过内容"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "labelPosition": "left",
- "defaultValue": false,
- "type": "boolean",
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {
- "onSelect": {
- "label": {
- "zh_CN": "勾选数据行的 Checkbox 时触发"
- },
- "description": {
- "zh_CN": "当用户手动勾选数据行的 Checkbox 时触发的事件"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "selection",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前选中项"
- }
- },
- {
- "name": "row",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前行"
- }
- }
- ],
- "returns": {}
- }
- },
- "onSelectAll": {
- "label": {
- "zh_CN": "勾选全选时触发"
- },
- "description": {
- "zh_CN": "当用户手动勾选全选 Checkbox 时触发的事件"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "selection",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前选中项"
- }
- }
- ],
- "returns": {}
- }
- },
- "onSelectionChange": {
- "label": {
- "zh_CN": "选择项发生变化时会触发"
- },
- "description": {
- "zh_CN": "当选择项发生变化时会触发该事件"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "selection",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前选中项"
- }
- }
- ],
- "returns": {}
- }
- },
- "onCellMouseEnter": {
- "label": {
- "zh_CN": "单元格 hover 时会触发"
- },
- "description": {
- "zh_CN": "当单元格 hover 进入时会触发该事件"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "row",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前行"
- }
- },
- {
- "name": "column",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前列"
- }
- },
- {
- "name": "cell",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前单元格"
- }
- },
- {
- "name": "event",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "原生事件 event"
- }
- }
- ],
- "returns": {}
- }
- },
- "onCellMouseLeave": {
- "label": {
- "zh_CN": "单元格 hover 退出时会触发"
- },
- "description": {
- "zh_CN": "当单元格 hover 退出时会触发该事件"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "row",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前行"
- }
- },
- {
- "name": "column",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前列"
- }
- },
- {
- "name": "cell",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前单元格"
- }
- },
- {
- "name": "event",
- "type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": "原生事件 event"
- }
- }
- ],
- "returns": {}
- }
- }
- },
- "slots": {
- "empty": {
- "label": {
- "zh_CN": "empty"
- },
- "description": {
- "zh_CN": "当数据为空时自定义的内容"
- }
- },
- "append": {
- "label": {
- "zh_CN": "append"
- },
- "description": {
- "zh_CN": "插入至表格最后一行之后的内容, 如果需要对表格的内容进行无限滚动操作,可能需要用到这个 slot。 若表格有合计行,该 slot 会位于合计行之上。"
- }
- }
- }
- }
- },
- {
- "id": 1,
- "version": "2.4.2",
- "name": {
- "zh_CN": "表单"
- },
- "component": "ElTableColumn",
- "icon": "table",
- "description": "用于展示多条结构类似的数据, 可对数据进行排序、筛选、对比或其他自定义操作",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "element-plus",
- "exportName": "ElTableColumn",
- "destructuring": true
- },
- "group": "表单组件",
- "category": "element-plus",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["inline", "label-width"]
- },
- "contextMenu": {
- "actions": ["copy", "remove", "insert", "updateAttr", "bindEvent", "createBlock"],
- "disable": []
- },
- "invalidity": [""],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": {},
- "slots": {}
- }
- },
{
"version": "3.20.0",
"name": {
@@ -3388,7 +229,6 @@
"required": true,
"readOnly": false,
"disabled": false,
- "defaultValue": "",
"cols": 12,
"bindState": false,
"widget": {
@@ -4145,15 +985,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onFocus": {
"label": {
@@ -4168,15 +1006,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onChange": {
"label": {
@@ -4191,15 +1027,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -4429,7 +1263,6 @@
{
"property": "src",
"type": "string",
- "defaultValue": "",
"bindState": true,
"label": {
"text": {
@@ -4539,8 +1372,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
@@ -4653,8 +1485,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
@@ -4764,8 +1595,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
@@ -4863,117 +1693,40 @@
"label": "post",
"value": "post"
}
- ]
- }
- },
- "description": {
- "zh_CN": "用于发送 form-data 的 HTTP 方法"
- }
- }
- ]
- }
- ],
- "events": {
- "onClick": {
- "label": {
- "zh_CN": "点击时触发"
- },
- "description": {
- "zh_CN": "点击时触发"
- },
- "type": "event",
- "functionInfo": {
- "params": [],
- "returns": {}
- },
- "defaultValue": ""
- }
- },
- "shortcuts": {
- "properties": []
- },
- "contentMenu": {
- "actions": []
- }
- },
- "configure": {
- "isContainer": true
- }
- },
- {
- "version": "1.0.0",
- "icon": "label",
- "name": {
- "zh_CN": "表单标签"
- },
- "component": "label",
- "container": false,
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "devMode": "proCode",
- "npm": {},
- "group": "component",
- "category": "html",
- "priority": 110,
- "schema": {
- "properties": [
- {
- "label": {
- "zh_CN": "基础信息"
- },
- "description": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "for",
- "label": {
- "text": {
- "zh_CN": "label绑定表单元素"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
- "description": {
- "zh_CN": "label 绑定到哪个表单元素"
- }
- },
- {
- "property": "form",
- "label": {
- "text": {
- "zh_CN": "label字段所属表单"
+ ]
}
},
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {}
- },
"description": {
- "zh_CN": "label 字段所属的一个或多个表单"
+ "zh_CN": "用于发送 form-data 的 HTTP 方法"
}
}
]
}
],
- "events": {},
+ "events": {
+ "onClick": {
+ "label": {
+ "zh_CN": "点击时触发"
+ },
+ "description": {
+ "zh_CN": "点击时触发"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ }
+ },
"shortcuts": {
"properties": []
},
"contentMenu": {
"actions": []
}
+ },
+ "configure": {
+ "isContainer": true
}
},
{
@@ -5624,15 +2377,13 @@
{
"name": "function",
"type": "Function",
- "defaultValue": "(valid) => {}",
"description": {
"zh_CN": "校验回调函数"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onInput": {
"label": {
@@ -5647,15 +2398,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框输入的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onBlur": {
"label": {
@@ -5670,15 +2419,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onFocus": {
"label": {
@@ -5693,15 +2440,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClear": {
"label": {
@@ -5714,8 +2459,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -5783,7 +2527,6 @@
"required": true,
"readOnly": false,
"disabled": false,
- "defaultValue": "标签",
"cols": 12,
"widget": {
"component": "InputConfigurator",
@@ -6182,7 +2925,6 @@
{
"property": "text",
"type": "string",
- "defaultValue": "按钮文案",
"label": {
"text": {
"zh_CN": "按钮文字"
@@ -6457,8 +3199,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -6744,15 +3485,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框改变后的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onInput": {
"label": {
@@ -6767,15 +3506,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框输入的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -6790,15 +3527,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onBlur": {
"label": {
@@ -6813,15 +3548,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onFocus": {
"label": {
@@ -6836,15 +3569,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClear": {
"label": {
@@ -6857,8 +3588,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
},
"slots": {
@@ -7086,10 +3816,231 @@
},
"onUpdate:modelValue": {
"label": {
- "zh_CN": "双向绑定的值改变时触发"
+ "zh_CN": "双向绑定的值改变时触发"
+ },
+ "description": {
+ "zh_CN": "当前选中的值改变时触发"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "value",
+ "type": "string",
+ "description": {
+ "zh_CN": "双向绑定的当前选中值"
+ }
+ }
+ ],
+ "returns": {}
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": ["visible", "width"]
+ },
+ "contextMenu": {
+ "actions": ["create symbol"],
+ "disable": ["copy", "remove"]
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "单选按钮组"
+ },
+ "component": "TinyRadioGroup",
+ "icon": "radio-group",
+ "description": "用于在一组选项中进行单选。",
+ "doc_url": "https://www.opentiny.design/tiny-vue/components/radio",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ },
+ "group": "component",
+ "configure": {
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "description": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "modelValue",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "单选框组的绑定值"
+ }
+ },
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "选项列表"
+ }
+ },
+ "defaultValue": [],
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "单选按钮选项列表,配置单选组的值、文本和点击事件。示例:[{label: '1', text: '选项1', events: {click: () => {console.log('点击选项1')}}}]"
+ }
+ },
+ {
+ "property": "disabled",
+ "label": {
+ "text": {
+ "zh_CN": "禁用"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "是否禁用整个单选组"
+ }
+ },
+ {
+ "property": "type",
+ "label": {
+ "text": {
+ "zh_CN": "展示形式"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "widget": {
+ "component": "ButtonGroupConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "radio",
+ "value": "radio"
+ },
+ {
+ "label": "button",
+ "value": "button"
+ }
+ ]
+ }
+ },
+ "description": {
+ "zh_CN": "单选组的展示形式,可选值为:radio(单选框) 、 button(按钮、选项式)"
+ }
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "medium",
+ "value": "medium"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ },
+ {
+ "label": "mini",
+ "value": "mini"
+ }
+ ]
+ }
+ },
+ "description": {
+ "zh_CN": "单选组尺寸, 可选值有 medium 、 small 、 mini"
+ }
+ },
+ {
+ "property": "vertical",
+ "label": {
+ "text": {
+ "zh_CN": "垂直排列"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "是否垂直展示单选按钮"
+ }
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onChange": {
+ "label": {
+ "zh_CN": "选中值变化时触发"
+ },
+ "description": {
+ "zh_CN": "选中值变化时触发"
+ },
+ "type": "event",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "value",
+ "type": "string",
+ "defaultValue": "",
+ "description": {
+ "zh_CN": "当前选中的值"
+ }
+ }
+ ],
+ "returns": {
+ }
+ }
+ },
+ "onUpdate:modelValue": {
+ "label": {
+ "zh_CN": "绑定值更新时触发"
},
"description": {
- "zh_CN": "当前选中的值改变时触发"
+ "zh_CN": "v-model 对应的值更新时触发"
},
"type": "event",
"functionInfo": {
@@ -7099,38 +4050,15 @@
"type": "string",
"defaultValue": "",
"description": {
- "zh_CN": "双向绑定的当前选中值"
+ "zh_CN": "更新后的绑定值"
}
}
],
- "returns": {}
- },
- "defaultValue": ""
+ "returns": {
+ }
+ }
}
}
- },
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": ["visible", "width"]
- },
- "contextMenu": {
- "actions": ["create symbol"],
- "disable": ["copy", "remove"]
- }
}
},
{
@@ -7274,6 +4202,7 @@
"readOnly": false,
"disabled": false,
"cols": 12,
+ "defaultValue": [],
"widget": {
"component": "CodeConfigurator",
"props": {
@@ -7285,6 +4214,16 @@
},
"labelPosition": "top"
},
+ {
+ "property": "tooltipConfig",
+ "defaultValue": { "always": false },
+ "label": {
+ "text": {
+ "zh_CN": "悬浮提示配置,默认不显示"
+ }
+ },
+ "required": false
+ },
{
"property": "multiple",
"label": {
@@ -7393,15 +4332,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "下拉框选中项的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -7416,15 +4353,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的当前选中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onBlur": {
"label": {
@@ -7439,15 +4374,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onFocus": {
"label": {
@@ -7462,15 +4395,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClear": {
"label": {
@@ -7483,8 +4414,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onRemoveTag": {
"label": {
@@ -7499,15 +4429,13 @@
{
"name": "value",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "被移除Tag对应数据项的值字段"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
},
"onBeforeMount": "console.log('table on load'); this.options = source.data"
@@ -7681,8 +4609,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -7697,15 +4624,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的开关状态值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -7931,7 +4856,6 @@
{
"name": "type",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "搜索类型,默认值为 {} "
}
@@ -7939,15 +4863,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前input框中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onSearch": {
"label": {
@@ -7962,7 +4884,6 @@
{
"name": "type",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "搜索类型,默认值为 {} "
}
@@ -7970,15 +4891,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前input框中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -8204,15 +5123,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "选中项的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -8227,15 +5144,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的当前选中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -8390,15 +5305,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "选中项的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -8413,15 +5326,13 @@
{
"name": "value",
"type": "array",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的当前选中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -8528,14 +5439,6 @@
"zh_CN": "选项列表"
}
},
- "defaultValue": [
- {
- "label": "标签2"
- },
- {
- "label": "标签2"
- }
- ],
"required": true,
"readOnly": false,
"disabled": false,
@@ -8599,15 +5502,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "选中项的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -8622,15 +5523,13 @@
{
"name": "value",
"type": "array",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的当前选中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -8864,8 +5763,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:visible": {
"label": {
@@ -8880,15 +5778,13 @@
{
"name": "value",
"type": "boolean",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的显示或隐藏的状态值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
},
"slots": {
@@ -8974,7 +5870,6 @@
"required": true,
"readOnly": false,
"disabled": false,
- "defaultValue": "",
"cols": 12,
"bindState": false,
"widget": {
@@ -9094,7 +5989,6 @@
{
"name": "component",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "当前点击的页签对象"
}
@@ -9102,15 +5996,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onEdit": {
"label": {
@@ -9125,7 +6017,6 @@
{
"name": "tab",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "当前操作的页签对象"
}
@@ -9133,15 +6024,13 @@
{
"name": "type",
"type": "String",
- "defaultValue": "",
"description": {
"zh_CN": "当前操作的类型(remove || add || edit)"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClose": {
"label": {
@@ -9156,15 +6045,13 @@
{
"name": "name",
"type": "String",
- "defaultValue": "",
"description": {
"zh_CN": "页签名称"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -9407,8 +6294,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -9590,15 +6476,13 @@
{
"name": "data",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前激活面板的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -9613,15 +6497,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -9807,7 +6689,7 @@
},
"onChange": "this.delProp('fetchData')",
"description": {
- "zh_CN": "设置表格的数据"
+ "zh_CN": "设置表格的数据(静态数据)。与 fetchData 互斥,配置其一即可"
},
"labelPosition": "top"
},
@@ -9815,7 +6697,7 @@
"property": "columns",
"label": {
"text": {
- "zh_CN": "表格列,需要优先于data生成"
+ "zh_CN": "表格列配置,需优先于 data 生成"
}
},
"required": true,
@@ -9831,7 +6713,6 @@
{
"property": "title",
"type": "string",
- "defaultValue": "",
"label": {
"text": {
"zh_CN": "列标题"
@@ -9845,10 +6726,9 @@
{
"property": "field",
"type": "string",
- "defaultValue": "",
"label": {
"text": {
- "zh_CN": "列键值"
+ "zh_CN": "列对应的数据字段名"
}
},
"widget": {
@@ -9859,10 +6739,9 @@
{
"property": "sortable",
"type": "boolean",
- "defaultValue": true,
"label": {
"text": {
- "zh_CN": "是否排序"
+ "zh_CN": "该列是否可排序,默认 false"
}
},
"widget": {
@@ -9874,10 +6753,9 @@
{
"property": "width",
"type": "string",
- "defaultValue": "",
"label": {
"text": {
- "zh_CN": "列宽"
+ "zh_CN": "列宽,可为整数、px、%、auto"
}
},
"widget": {
@@ -9888,7 +6766,6 @@
{
"property": "formatText",
"type": "string",
- "defaultValue": "",
"label": {
"text": {
"zh_CN": "内置渲染器"
@@ -9933,6 +6810,30 @@
{
"label": "省略",
"value": "ellipsis"
+ },
+ {
+ "label": "枚举",
+ "value": "enum"
+ },
+ {
+ "label": "下拉",
+ "value": "select"
+ },
+ {
+ "label": "文件大小",
+ "value": "filesize"
+ },
+ {
+ "label": "长日期时间",
+ "value": "longDateTime"
+ },
+ {
+ "label": "长时间",
+ "value": "longTime"
+ },
+ {
+ "label": "年月",
+ "value": "yearMonth"
}
]
}
@@ -9941,10 +6842,9 @@
{
"property": "renderer",
"type": "object",
- "defaultValue": "",
"label": {
"text": {
- "zh_CN": "渲染函数"
+ "zh_CN": "列渲染配置函数,自定义渲染内容,优先级高于formatText"
}
},
"widget": {
@@ -9957,7 +6857,6 @@
{
"property": "slots",
"type": "object",
- "defaultValue": "",
"label": {
"text": {
"zh_CN": "插槽"
@@ -10004,13 +6903,17 @@
{
"label": "展开列",
"value": "expand"
+ },
+ {
+ "label": "操作列",
+ "value": "operation"
}
],
"clearable": true
}
},
"description": {
- "zh_CN": "设置内置列的类型,该属性的可选值为 index(序号)、 selection(复选框)、 radio(单选框)、 expand(展开行)"
+ "zh_CN": "内置列类型:index(序号)、selection(复选)、radio(单选)、expand(展开行)、operation(操作列)"
},
"labelPosition": "left"
},
@@ -10107,7 +7010,7 @@
}
},
"description": {
- "zh_CN": "表格列的配置信息,需要优先于data生成"
+ "zh_CN": "表格列配置,需优先于 data 生成。列常用字段:title/field/width/type/sortable/showOverflow"
},
"labelPosition": "left"
},
@@ -10131,7 +7034,7 @@
}
},
"description": {
- "zh_CN": "服务端数据查询方法"
+ "zh_CN": "服务端数据查询方法,如 { api: () => Promise }。与 data 互斥,需配合 pager 使用"
},
"labelPosition": "top"
},
@@ -10146,11 +7049,6 @@
"readOnly": false,
"disabled": false,
"cols": 12,
- "defaultValue": {
- "attrs": {
- "currentPage": 1
- }
- },
"widget": {
"component": "CodeConfigurator",
"props": {
@@ -10159,7 +7057,7 @@
}
},
"description": {
- "zh_CN": "分页配置,需结合fetchData使用"
+ "zh_CN": "分页配置,需结合 fetchData。写法如 { attrs: { currentPage 当前页, pageSize 每页条数, pageSizes 可选每页条数数组, total 总条数, layout 布局如 \"total, prev, pager, next, jumper\" } }"
},
"labelPosition": "top"
},
@@ -10179,7 +7077,7 @@
"props": {}
},
"description": {
- "zh_CN": "是否允许调整列宽"
+ "zh_CN": "是否允许调整列宽,默认 true"
},
"labelPosition": "left"
},
@@ -10201,7 +7099,7 @@
}
},
"description": {
- "zh_CN": "自定义行数据唯一主键的字段名(行数据必须要有唯一主键,默认自动生成)"
+ "zh_CN": "自定义行数据唯一主键字段名(默认 _RID,行数据需有唯一主键,默认自动生成)"
},
"labelPosition": "left"
},
@@ -10223,7 +7121,7 @@
}
},
"description": {
- "zh_CN": "表格行数据复选框配置项"
+ "zh_CN": "行复选框配置,需配合列 type=selection。常用字段:trigger 勾选触发方式(cell 点单元格 / row 点整行,默认点复选框图标);labelField 复选框旁显示的字段名;checkRowKeys 初始化默认勾选的行主键数组(依赖 row-id);checkMethod函数配置是否可选 返回 false 则该行不可勾选;checkAll 初始化是否全选;showHeader 表头是否显示全选框;"
}
},
{
@@ -10242,7 +7140,7 @@
"props": {}
},
"description": {
- "zh_CN": "表格校验规则配置项"
+ "zh_CN": "编辑校验规则,配合 edit-config 与列 editor 使用。按字段名配置规则数组,如 { name: [{ required: true, message: \"必填\" }, { min: 2, max: 10, message: \"长度 2-10\" }] }"
},
"labelPosition": "top"
},
@@ -10262,7 +7160,7 @@
"props": {}
},
"description": {
- "zh_CN": "表格编辑配置项"
+ "zh_CN": "表格编辑配置。常用字段:trigger 激活方式(click / dblclick / manual);mode 编辑粒度(cell 单元格 / row 整行);showStatus 是否显示编辑状态标记;activeMethod({row, column}) 返回 false 则禁止编辑该单元格/行"
},
"labelPosition": "top"
},
@@ -10282,7 +7180,7 @@
"props": {}
},
"description": {
- "zh_CN": "展开行配置项"
+ "zh_CN": "展开行配置,需配合列 type=expand。常用字段:expandAll 是否默认展开全部;trigger 展开触发方式(default 点图标 / cell 点单元格 / row 点整行);expandRowKeys 默认展开的行主键数组(依赖 row-id);accordion 同级是否只能展开一行;activeMethod({row}) 返回 false 则不渲染该行展开区;showIcon 是否显示展开图标"
},
"labelPosition": "top"
},
@@ -10372,47 +7270,7 @@
"props": {}
},
"description": {
- "zh_CN": "设置行序号是否连续,开启分页时有效,该属性的默认值为 false"
- },
- "labelPosition": "left"
- },
- {
- "property": "highlight-current-row",
- "label": {
- "text": {
- "zh_CN": "高亮当前行"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "description": {
- "zh_CN": "高亮当前行"
- },
- "labelPosition": "left"
- },
- {
- "property": "highlight-hover-row",
- "label": {
- "text": {
- "zh_CN": "移入行高亮"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {}
- },
- "description": {
- "zh_CN": "鼠标移到行是否要高亮显示"
+ "zh_CN": "行序号是否连续,开启分页时有效,默认 false"
},
"labelPosition": "left"
},
@@ -10420,7 +7278,7 @@
"property": "row-class-name",
"label": {
"text": {
- "zh_CN": "设置行高亮"
+ "zh_CN": "行类名"
}
},
"required": true,
@@ -10432,7 +7290,7 @@
"props": {}
},
"description": {
- "zh_CN": "给行附加 className,也可以是函数 Function({seq, row, rowIndex, $rowIndex})"
+ "zh_CN": "给行附加 className,可为 string 或函数 ({seq, row, rowIndex, $rowIndex, column, columnIndex}) => string"
},
"labelPosition": "top"
},
@@ -10452,14 +7310,14 @@
"props": {}
},
"description": {
- "zh_CN": "设置表格内容区域(不含表格头部,底部)的最大高度。"
+ "zh_CN": "表格内容区(不含表头/表尾)最大高度,支持整数、px、%"
}
},
{
"property": "row-span",
"label": {
"text": {
- "zh_CN": "行合并"
+ "zh_CN": "简易行合并"
}
},
"required": true,
@@ -10471,7 +7329,7 @@
"props": {}
},
"description": {
- "zh_CN": "设置行合并,该属性仅适用于普通表格,不可与 tree-config 同时使用"
+ "zh_CN": "简易行合并:传入要合并的字段列表,如 [{ field: \"area\" }, { field: \"province\" }],相邻且值相同的单元格会自动合并。仅普通表格可用,不可与 tree-config 同用;更复杂合并请用 span-method"
},
"labelPosition": "top"
}
@@ -10481,49 +7339,45 @@
"events": {
"onFilterChange": {
"label": {
- "zh_CN": "筛选条件改变时触发改事件"
+ "zh_CN": "筛选条件改变时触发"
},
"description": {
- "zh_CN": "配置 remote-filter 开启服务端过滤,服务端过滤会调用表格 fetch-data 进行查询,filter-change 服务端过滤后触发的事件"
+ "zh_CN": "当筛选条件发生变化时触发。开启 remote-filter 时会走服务端过滤并调用 fetch-data"
},
"type": "event",
"functionInfo": {
"params": [
{
- "name": "table",
+ "name": "args",
"type": "Object",
- "defaultValue": "",
"description": {
- "zh_CN": "{$table,filters} 包含 table 实例对象和过滤条件的对象"
+ "zh_CN": "{$table(表格实例), filters(过滤条件)}"
}
}
],
"returns": {}
- },
- "defaultValue": "function onClick(e) {}"
+ }
},
"onSortChange": {
"label": {
- "zh_CN": "点击列头,执行数据排序前触发的事件"
+ "zh_CN": "排序改变时触发"
},
"description": {
- "zh_CN": "配置 remote-filter 开启服务端过滤,服务端过滤会调用表格 fetch-data 进行查询,filter-change 服务端过滤后触发的事件"
+ "zh_CN": "点击列头执行数据排序前触发。开启 remote-sort 时会走服务端排序并调用 fetch-data"
},
"type": "event",
"functionInfo": {
"params": [
{
- "name": "table",
+ "name": "args",
"type": "Object",
- "defaultValue": "",
"description": {
- "zh_CN": "{$table,filters} 包含 table 实例对象和过滤条件的对象"
+ "zh_CN": "{$table(表格实例), field(排序字段), order(排序方向)},order 为 asc|desc"
}
}
],
"returns": {}
- },
- "defaultValue": "function onClick(e) {}"
+ }
},
"onSelectAll": {
"label": {
@@ -10536,33 +7390,22 @@
"functionInfo": {
"params": [
{
- "name": "table",
+ "name": "args",
"type": "Object",
- "defaultValue": "",
- "description": {
- "zh_CN": " 包含 table 实例对象"
- }
- },
- {
- "name": "checked",
- "type": "boolean",
- "defaultValue": "",
"description": {
- "zh_CN": "勾选状态"
+ "zh_CN": "{$table(表格实例), checked(是否选中), selection(选中数据), row(选中行数据)}"
}
},
{
- "name": "selction",
- "type": "Array",
- "defaultValue": "",
+ "name": "event",
+ "type": "Event",
"description": {
- "zh_CN": "选中的表格数据数组"
+ "zh_CN": "原生 Event"
}
}
],
"returns": {}
- },
- "defaultValue": "function onClick(e) {}"
+ }
},
"onSelectChange": {
"label": {
@@ -10575,70 +7418,50 @@
"functionInfo": {
"params": [
{
- "name": "table",
+ "name": "args",
"type": "Object",
- "defaultValue": "",
"description": {
- "zh_CN": " table 实例对象"
+ "zh_CN": "表格选中相关信息对象, { $table(表格实例), selection(选中数据), row(选中行数据), checked(是否选中), rowIndex(选中行索引) }"
}
},
{
"name": "event",
- "type": "Object",
- "defaultValue": "",
+ "type": "Event",
"description": {
- "zh_CN": " 原生 Event"
+ "zh_CN": "原生 Event"
}
}
],
"returns": {}
- },
- "defaultValue": "function onClick(e) {}"
+ }
},
"onToggleExpandChange": {
"label": {
- "zh_CN": "当行展开或收起时会触发该事件"
+ "zh_CN": "展开行切换时触发"
},
"description": {
- "zh_CN": "当行展开或收起时会触发该事件"
+ "zh_CN": "当行展开或收起时触发"
},
"type": "event",
"functionInfo": {
"params": [
{
- "name": "table",
+ "name": "args",
"type": "Object",
- "defaultValue": "",
"description": {
- "zh_CN": "{$table,row,rowIndex} 包含 table 实例对象和当前行数据的对象"
+ "zh_CN": "{$table(表格实例), row(行数据), rowIndex(行索引)}"
}
},
{
"name": "event",
- "type": "Object",
- "defaultValue": "",
+ "type": "Event",
"description": {
- "zh_CN": " 原生 Event"
+ "zh_CN": "原生 Event"
}
}
],
"returns": {}
- },
- "defaultValue": "function onClick(e) {}"
- },
- "onCurrentChange": {
- "label": {
- "zh_CN": "行点击时触发"
- },
- "description": {
- "zh_CN": "行点击时触发"
- },
- "type": "event",
- "functionInfo": {
- "params": [],
- "returns": {}
- },
- "defaultValue": ""
+ }
}
},
"shortcuts": {
@@ -10843,7 +7666,6 @@
"readOnly": false,
"disabled": false,
"cols": 12,
- "defaultValue": "total,sizes,prev, pager, next",
"widget": {
"component": "InputConfigurator",
"props": {
@@ -10872,15 +7694,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前页的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onPrevClick ": {
"label": {
@@ -10895,15 +7715,13 @@
{
"name": "page",
"type": "String",
- "defaultValue": "",
"description": {
"zh_CN": "当前页的页码值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onNextClick": {
"label": {
@@ -10918,15 +7736,13 @@
{
"name": "page",
"type": "String",
- "defaultValue": "",
"description": {
"zh_CN": "当前页的页码值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -11075,7 +7891,6 @@
"readOnly": false,
"disabled": false,
"cols": 12,
- "defaultValue": true,
"widget": {
"component": "CheckBoxConfigurator",
"props": {}
@@ -11232,7 +8047,6 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中项的值"
}
@@ -11240,15 +8054,13 @@
{
"name": "value",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中对象"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -11263,15 +8075,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的当前选中值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClose": {
"label": {
@@ -11284,8 +8094,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onPageChange": {
"label": {
@@ -11300,15 +8109,13 @@
{
"name": "value",
"type": "String",
- "defaultValue": "",
"description": {
"zh_CN": "当前页码数"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -11396,16 +8203,6 @@
"required": true,
"readOnly": false,
"disabled": false,
- "defaultValue": [
- {
- "label": "一级 1",
- "children": [
- {
- "label": "二级 1-1"
- }
- ]
- }
- ],
"cols": 12,
"widget": {
"component": "CodeConfigurator",
@@ -11586,7 +8383,6 @@
{
"name": "data",
"type": "object",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中节点信息"
}
@@ -11594,15 +8390,13 @@
{
"name": "currentNode",
"type": "object",
- "defaultValue": "",
"description": {
"zh_CN": "树组件目前的选中状态信息,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onNodeClick": {
"label": {
@@ -11617,7 +8411,6 @@
{
"name": "data",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "当前选中节点信息"
}
@@ -11625,7 +8418,6 @@
{
"name": "node",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "树组件目前的选中状态信息,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性"
}
@@ -11633,15 +8425,13 @@
{
"name": "vm",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "树组件实例"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -11702,12 +8492,6 @@
{
"property": "vertical",
"type": "Boolean",
- "defaultValue": {
- "type": "i18n",
- "zh_CN": "垂直布局",
- "en_US": "layout",
- "key": ""
- },
"label": {
"text": {
"zh_CN": "垂直布局"
@@ -11754,24 +8538,10 @@
"text": {
"zh_CN": "步骤条数据"
}
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "defaultValue": [
- {
- "name": "配置基本信息",
- "status": "ready"
- },
- {
- "name": "配置报价",
- "status": "wait"
- },
- {
- "name": "完成报价",
- "status": "wait"
- }
- ],
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
"cols": 12,
"widget": {
"component": "CodeConfigurator",
@@ -11801,7 +8571,6 @@
{
"name": "type",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "点击节点的下标"
}
@@ -11809,15 +8578,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "当前节点对象:{ name: 节点名称, time: 时间 }"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -11956,7 +8723,6 @@
"required": true,
"readOnly": false,
"disabled": false,
- "defaultValue": "提示信息",
"cols": 12,
"widget": {
"component": "InputConfigurator",
@@ -11996,7 +8762,6 @@
"zh_CN": "是否可见"
}
},
- "defaultValue": true,
"cols": 12,
"widget": {
"component": "CheckBoxConfigurator",
@@ -12014,7 +8779,6 @@
"zh_CN": "手动控制"
}
},
- "defaultValue": true,
"widget": {
"component": "CheckBoxConfigurator",
"props": {}
@@ -12520,15 +9284,13 @@
{
"name": "value",
"type": "boolean",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的可见状态值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -12557,6 +9319,94 @@
}
}
},
+ {
+ "name": {
+ "zh_CN": "卡片组件"
+ },
+ "component": "TinyCard",
+ "icon": "card",
+ "description": "强大卡片组件,用于包裹展示内容。",
+ "doc_url": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "dev_mode": "proCode",
+ "npm": {
+ },
+ "group": "component",
+ "configure": {
+ },
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "description": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "auto-width",
+ "label": {
+ "text": {
+ "zh_CN": "自动撑开"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "卡片的宽度是否自动撑开,设置后将不再给卡片设置固定宽度"
+ }
+ },
+ {
+ "property": "type",
+ "label": {
+ "text": {
+ "zh_CN": "卡片类型"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "设置卡片类型,可选值为\"text\", \"image\", \"video\", \"logo\", 默认是\"text\""
+ }
+ },
+ {
+ "property": "src",
+ "label": {
+ "text": {
+ "zh_CN": "图片或者视频的地址"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "图片或者视频的地址"
+ }
+ },
+ {
+ "property": "title",
+ "label": {
+ "text": {
+ "zh_CN": "卡片的标题,字号比正文略大,比h3小"
+ }
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "description": {
+ "zh_CN": "卡片的标题,字号比正文略大,比h3小"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ },
{
"version": "3.20.0",
"name": {
@@ -12828,15 +9678,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框改变后的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onInput": {
"label": {
@@ -12851,15 +9699,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框输入的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -12874,15 +9720,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onBlur": {
"label": {
@@ -12897,15 +9741,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onFocus": {
"label": {
@@ -12920,15 +9762,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClear": {
"label": {
@@ -12941,8 +9781,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -13269,15 +10108,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框改变后的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onInput": {
"label": {
@@ -13292,15 +10129,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "输入框输入的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onUpdate:modelValue": {
"label": {
@@ -13315,15 +10150,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "双向绑定的值"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onBlur": {
"label": {
@@ -13338,15 +10171,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onFocus": {
"label": {
@@ -13361,15 +10192,13 @@
{
"name": "event",
"type": "Object",
- "defaultValue": "",
"description": {
"zh_CN": "原生 event"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onClear": {
"label": {
@@ -13382,8 +10211,7 @@
"functionInfo": {
"params": [],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -13595,15 +10423,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "右侧列表元素变化时触发"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onLeftCheckChange": {
"label": {
@@ -13618,15 +10444,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "左侧列表元素被用户选中 / 取消选中时触发;"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
},
"onRightCheckChange": {
"label": {
@@ -13641,15 +10465,13 @@
{
"name": "value",
"type": "string",
- "defaultValue": "",
"description": {
"zh_CN": "右侧列表元素被用户选中 / 取消选中时触发"
}
}
],
"returns": {}
- },
- "defaultValue": ""
+ }
}
}
},
@@ -13774,30 +10596,6 @@
"zh_CN": "基础元素"
},
"children": [
- {
- "name": {
- "zh_CN": "段落"
- },
- "icon": "paragraph",
- "screenshot": "",
- "snippetName": "p",
- "schema": {
- "componentName": "p",
- "children": "您好!欢迎使用生成式UI。它将重塑大模型交互方式,打造极致顺滑的智能体验。"
- }
- },
- {
- "name": {
- "zh_CN": "链接"
- },
- "icon": "link",
- "screenshot": "",
- "snippetName": "a",
- "schema": {
- "componentName": "a",
- "children": "链接"
- }
- },
{
"name": {
"zh_CN": "分隔线"
@@ -13807,36 +10605,6 @@
"snippetName": "hr",
"schema": {}
},
- {
- "name": {
- "zh_CN": "标题"
- },
- "icon": "h16",
- "screenshot": "",
- "snippetName": "h1",
- "schema": {
- "componentName": "h1",
- "props": {},
- "children": "Heading"
- }
- },
- {
- "name": {
- "zh_CN": "视频"
- },
- "icon": "video",
- "screenshot": "",
- "snippetName": "video",
- "schema": {
- "componentName": "video",
- "props": {
- "src": "https://tinyengine-assets.obs.myhuaweicloud.com/files/in-action.mp4#t=1.5",
- "width": "200",
- "height": "100",
- "style": "border:1px solid #ccc"
- }
- }
- },
{
"name": {
"zh_CN": "按钮"
@@ -13851,44 +10619,6 @@
}
}
},
- {
- "name": {
- "zh_CN": "按钮组"
- },
- "icon": "buttons",
- "snippetName": "TinyButtons",
- "screenshot": "",
- "schema": {
- "componentName": "div",
- "props": {},
- "children": [
- {
- "componentName": "TinyButton",
- "props": {
- "text": "提交",
- "type": "primary",
- "style": "margin: 0 5px 0 5px;"
- }
- },
- {
- "componentName": "TinyButton",
- "props": {
- "text": "重置",
- "style": "margin: 0 5px 0 5px;"
- }
- },
- {
- "componentName": "TinyButton",
- "props": {
- "text": "取消"
- }
- }
- ]
- },
- "configure": {
- "isContainer": true
- }
- },
{
"name": {
"zh_CN": "互斥按钮组"
@@ -14133,6 +10863,59 @@
}
}
},
+ {
+ "name": {
+ "zh_CN": "基础单选组"
+ },
+ "snippetName": "TinyRadioGroup",
+ "schema": {
+ "componentName": "TinyRadioGroup",
+ "props": {
+ "modelValue": "1",
+ "options": [
+ {
+ "label": "1",
+ "text": "选项1"
+ },
+ {
+ "label": "2",
+ "text": "选项2"
+ },
+ {
+ "label": "3",
+ "text": "选项3"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "选项式单选组"
+ },
+ "snippetName": "TinyRadioGroup",
+ "schema": {
+ "componentName": "TinyRadioGroup",
+ "props": {
+ "modelValue": "2",
+ "type": "button",
+ "options": [
+ {
+ "label": "1",
+ "text": "选项1"
+ },
+ {
+ "label": "2",
+ "text": "选项2"
+ },
+ {
+ "label": "3",
+ "text": "选项3"
+ }
+ ]
+ }
+ }
+ },
{
"name": {
"zh_CN": "复选框"
@@ -14642,6 +11425,91 @@
}
]
}
+ },
+ {
+ "name": {
+ "zh_CN": "内容展示卡片"
+ },
+ "snippetName": "TinyCard",
+ "schema": {
+ "componentName": "TinyCard",
+ "children": [
+ {
+ "componentName": "h2",
+ "children": "员工信息列表"
+ },
+ {
+ "componentName": "TinyGrid",
+ "props": {
+ "editConfig": {
+ "trigger": "click",
+ "mode": "cell",
+ "showStatus": true
+ },
+ "columns": [
+ {
+ "type": "index",
+ "width": 60
+ },
+ {
+ "type": "selection",
+ "width": 60
+ },
+ {
+ "field": "employees",
+ "title": "员工数"
+ },
+ {
+ "field": "created_date",
+ "title": "创建日期"
+ },
+ {
+ "field": "city",
+ "title": "城市"
+ }
+ ],
+ "data": [
+ {
+ "id": "1",
+ "name": "GFD科技有限公司",
+ "city": "福州",
+ "employees": 800,
+ "created_date": "2014-04-30 00:56:00",
+ "boole": false
+ },
+ {
+ "id": "2",
+ "name": "WWW科技有限公司",
+ "city": "深圳",
+ "employees": 300,
+ "created_date": "2016-07-08 12:36:22",
+ "boole": true
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "图片卡片"
+ },
+ "snippetName": "TinyCard",
+ "schema": {
+ "componentName": "TinyCard",
+ "props": {
+ "title": "卡片标题",
+ "type": "image",
+ "src": "https://res.hc-cdn.com/tiny-vue-web-doc/3.26.1/static/images/dsj.png"
+ },
+ "children": [
+ {
+ "componentName": "p",
+ "children": "这是一段长文本内容,这是一段长文本内容,这是一段长文本内容,这是一段长文本内容。"
+ }
+ ]
+ }
}
]
},
diff --git a/packages/materials/vue-opentiny-vue/src/meta/materials/chart.json b/packages/materials/vue-opentiny-vue/src/meta/materials/chart.json
new file mode 100644
index 00000000..f0958216
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/materials/chart.json
@@ -0,0 +1,4647 @@
+{
+ "data": {
+ "framework": "Vue",
+ "materials": {
+ "components": [
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "折线图"
+ },
+ "component": "TinyHuichartsLine",
+ "icon": "line",
+ "description": "折线图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "dataZoom",
+ "label": {
+ "text": {
+ "zh_CN": "区域缩放轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "数据点文本样式"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "padding",
+ "label": {
+ "text": {
+ "zh_CN": "图表内边距"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "xAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置x轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "默认值:图表数据data中data[0]对象的第一个key值"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "yAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置y轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "折线图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "柱状图"
+ },
+ "component": "TinyHuichartsHistogram",
+ "icon": "histogram",
+ "description": "柱状图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsHistogram",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [{ "Month": "", "val": "" }],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "dataRules",
+ "label": {
+ "text": {
+ "zh_CN": "数据规则"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "dataZoom",
+ "label": {
+ "text": {
+ "zh_CN": "区域缩放轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "direction",
+ "label": {
+ "text": {
+ "zh_CN": "柱体方向"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "language": "json",
+ "options": [
+ {
+ "label": "vertical",
+ "value": "vertical"
+ },
+ {
+ "label": "horizontal",
+ "value": "horizontal"
+ }
+ ]
+ }
+ },
+ "description": {
+ "zh_CN": "柱体方向"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "柱体样式"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "label",
+ "label": {
+ "text": {
+ "zh_CN": "柱体文本"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "柱体文本,默认不显示"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "legend",
+ "label": {
+ "text": {
+ "zh_CN": "图例配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图例配置,默认显示"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "lineDataName",
+ "label": {
+ "text": {
+ "zh_CN": "更改数据名"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "柱状图更改为折线图的数据名"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "markline",
+ "label": {
+ "text": {
+ "zh_CN": "阈值线配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "padding",
+ "label": {
+ "text": {
+ "zh_CN": "图表内边距"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "type",
+ "label": {
+ "text": {
+ "zh_CN": "柱状图类型"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "bar",
+ "value": "bar"
+ },
+ {
+ "label": "range",
+ "value": "range"
+ },
+ {
+ "label": "water-fall",
+ "value": "water-fall"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "xAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置x轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": { "data": "" },
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "默认值:图表数据data中data[0]对象的第一个key值"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "yAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置y轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "柱状图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onReady": {
+ "type": "event",
+ "label": {
+ "zh_CN": "每次渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,每次渲染都会触发一次"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ },
+ "onReadyOnce": {
+ "type": "event",
+ "label": {
+ "zh_CN": "首次渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,只会在首次渲染完成后触发"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "条形图"
+ },
+ "component": "TinyHuichartsBar",
+ "icon": "bar",
+ "description": "条形图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsBar",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "dataZoom",
+ "label": {
+ "text": {
+ "zh_CN": "区域缩放轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "柱体样式"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "padding",
+ "label": {
+ "text": {
+ "zh_CN": "图表内边距"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "xAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置x轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "默认值:图表数据data中data[0]对象的第一个key值"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "yAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置y轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "条形图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onReady": {
+ "type": "event",
+ "label": {
+ "zh_CN": "图表渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,每次渲染都会触发一次"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ },
+ "onReadyOnce": {
+ "type": "event",
+ "label": {
+ "zh_CN": "图表渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,只会在首次渲染完成后触发"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "圆盘图"
+ },
+ "component": "TinyHuichartsPie",
+ "icon": "pie",
+ "description": "圆盘图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsPie",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "title",
+ "label": {
+ "text": {
+ "zh_CN": "中心文本配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "描边配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "position",
+ "label": {
+ "text": {
+ "zh_CN": "图表位置及大小"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "圆盘图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "环形图"
+ },
+ "component": "TinyHuichartsRing",
+ "icon": "ring",
+ "description": "环形图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsRing",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "position",
+ "label": {
+ "text": {
+ "zh_CN": "图表位置及大小"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "描边配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "title",
+ "label": {
+ "text": {
+ "zh_CN": "中心文本配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "环形图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onReady": {
+ "type": "event",
+ "label": {
+ "zh_CN": "图表渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,每次渲染都会触发一次"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ },
+ "onReadyOnce": {
+ "type": "event",
+ "label": {
+ "zh_CN": "图表渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,只会在首次渲染完成后触发"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ }
+ },
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "默认内容"
+ },
+ "description": {
+ "zh_CN": "组件默认插槽"
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "雷达图"
+ },
+ "component": "TinyHuichartsRadar",
+ "icon": "radar",
+ "description": "雷达图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsRadar",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "area",
+ "label": {
+ "text": {
+ "zh_CN": "图形区域配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "radar",
+ "label": {
+ "text": {
+ "zh_CN": "坐标系配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {
+ "triggerEvent": true
+ },
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "position",
+ "label": {
+ "text": {
+ "zh_CN": "图表位置及大小"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "雷达图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {
+ "onReady": {
+ "type": "event",
+ "label": {
+ "zh_CN": "图表渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,每次渲染都会触发一次"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ },
+ "onReadyOnce": {
+ "type": "event",
+ "label": {
+ "zh_CN": "图表渲染完成后触发"
+ },
+ "description": {
+ "zh_CN": "图表渲染完成后触发,只会在首次渲染完成后触发"
+ },
+ "functionInfo": {
+ "params": [],
+ "returns": {}
+ }
+ }
+ },
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "默认内容"
+ },
+ "description": {
+ "zh_CN": "组件默认插槽"
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "漏斗图"
+ },
+ "component": "TinyHuichartsFunnel",
+ "icon": "funnel",
+ "description": "漏斗图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsFunnel",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "position",
+ "label": {
+ "text": {
+ "zh_CN": "图表位置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "size",
+ "label": {
+ "text": {
+ "zh_CN": "图表大小"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "漏斗图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "散点图"
+ },
+ "component": "TinyHuichartsScatter",
+ "icon": "scatter",
+ "description": "散点图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsScatter",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "bubbleSize",
+ "label": {
+ "text": {
+ "zh_CN": "气泡大小范围"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "节点图形样式"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "padding",
+ "label": {
+ "text": {
+ "zh_CN": "图表内边距"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "xAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置x轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "默认值:图表数据data中data[0]对象的第一个key值"
+ },
+ "labelPosition": "left",
+ "defaultValue": {}
+ },
+ {
+ "property": "yAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置y轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left",
+ "defaultValue": {}
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "散点图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "瀑布图"
+ },
+ "component": "TinyHuichartsWaterfall",
+ "icon": "waterfall",
+ "description": "瀑布图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsWaterfall",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "dataZoom",
+ "label": {
+ "text": {
+ "zh_CN": "区域缩放轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "itemStyle",
+ "label": {
+ "text": {
+ "zh_CN": "柱体样式"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "padding",
+ "label": {
+ "text": {
+ "zh_CN": "图表内边距"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "xAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置x轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "默认值:图表数据data中data[0]对象的第一个key值"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "yAxis",
+ "label": {
+ "text": {
+ "zh_CN": "配置y轴"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": {},
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "瀑布图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "仪表盘"
+ },
+ "component": "TinyHuichartsGauge",
+ "icon": "gauge",
+ "description": "仪表盘",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsGauge",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "startAngle",
+ "label": {
+ "text": {
+ "zh_CN": "起始角度"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "仪表盘起始角度。圆心正右手侧为 0 度,正上方为 90 度,正左手侧为 180 度"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "endAngle",
+ "label": {
+ "text": {
+ "zh_CN": "结束角度"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "仪表盘结束角度。圆心正右手侧为 0 度,正上方为 90 度,正左手侧为 180 度"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "min",
+ "label": {
+ "text": {
+ "zh_CN": "最小刻度"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "仪表盘的最小值"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "max",
+ "label": {
+ "text": {
+ "zh_CN": "最大刻度"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "仪表盘的最大值"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "pointer",
+ "label": {
+ "text": {
+ "zh_CN": "刻度指针"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "boolean",
+ "widget": {
+ "component": "SwitchConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "刻度指针是否显示"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "splitColor",
+ "label": {
+ "text": {
+ "zh_CN": "分割区间"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "仪表盘的分割颜色,splitColor[i][0] 的值代表整根轴线的百分比,应在 0 到 1 之间, splitColor[i][1] 是对应的颜色"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "仪表盘配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "拓扑图"
+ },
+ "component": "TinyHuichartsGraph",
+ "icon": "graph",
+ "description": "拓扑图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsGraph",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "series",
+ "label": {
+ "text": {
+ "zh_CN": "系列"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "animationEasing",
+ "label": {
+ "text": {
+ "zh_CN": "初始缓动效果"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "初始动画的缓动效果"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "animationEasingUpdate",
+ "label": {
+ "text": {
+ "zh_CN": "更新缓动效果"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "string",
+ "widget": {
+ "component": "InputConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "更新动画的缓动效果"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "animationDurationUpdate",
+ "label": {
+ "text": {
+ "zh_CN": "动画时长"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "数据更新动画的时长"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "animationDelayUpdate",
+ "label": {
+ "text": {
+ "zh_CN": "动画延迟"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "type": "number",
+ "widget": {
+ "component": "NumberConfigurator",
+ "props": {}
+ },
+ "description": {
+ "zh_CN": "数据更新动画的延迟"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "拓扑图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "进度图"
+ },
+ "component": "TinyHuichartsProcess",
+ "icon": "process",
+ "description": "进度图",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "destructuring": true,
+ "exportName": "TinyHuichartsProcess",
+ "name": "TinyVueHuicharts组件库",
+ "package": "@opentiny/vue-huicharts",
+ "version": "3.22.0",
+ "script": "https://registry.npmmirror.com/@opentiny/vue-runtime/3.22/files/dist3/tiny-vue-huicharts.mjs"
+ },
+ "group": "chart",
+ "category": "图表组件",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础信息"
+ },
+ "description": {
+ "zh_CN": "基础信息"
+ },
+ "content": [
+ {
+ "property": "options",
+ "label": {
+ "text": {
+ "zh_CN": "图表配置"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "默认分组"
+ },
+ "content": [
+ {
+ "property": "color",
+ "label": {
+ "text": {
+ "zh_CN": "颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "颜色, 类型Array"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "data",
+ "label": {
+ "text": {
+ "zh_CN": "数据"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "defaultValue": [],
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "图表数据"
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "name",
+ "label": {
+ "text": {
+ "zh_CN": "图表数据, 已有默认值,禁止设置name"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "state",
+ "label": {
+ "text": {
+ "zh_CN": "根据状态设置颜色"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "padding",
+ "label": {
+ "text": {
+ "zh_CN": "图表内边距"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "theme",
+ "label": {
+ "text": {
+ "zh_CN": "主题"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "SelectConfigurator",
+ "props": {
+ "options": [
+ {
+ "label": "light",
+ "value": "light"
+ },
+ {
+ "label": "dark",
+ "value": "dark"
+ },
+ {
+ "label": "hdesign-light",
+ "value": "hdesign-light"
+ },
+ {
+ "label": "hdesign-dark",
+ "value": "hdesign-dark"
+ },
+ {
+ "label": "cloud-light",
+ "value": "cloud-light"
+ },
+ {
+ "label": "bpit-light",
+ "value": "bpit-light"
+ },
+ {
+ "label": "bpit-dark",
+ "value": "bpit-dark"
+ }
+ ]
+ }
+ },
+ "labelPosition": "left"
+ },
+ {
+ "property": "tooltip",
+ "label": {
+ "text": {
+ "zh_CN": "悬浮框内容"
+ }
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "cols": 12,
+ "widget": {
+ "component": "CodeConfigurator",
+ "props": {
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "悬浮提示框内容配置"
+ },
+ "labelPosition": "left"
+ }
+ ]
+ }
+ ],
+ "widget": {
+ "component": "NestedPropertyConfigurator",
+ "props": {
+ "type": "object",
+ "language": "json"
+ }
+ },
+ "description": {
+ "zh_CN": "进度图配置"
+ },
+ "labelPosition": "top"
+ }
+ ]
+ }
+ ],
+ "events": {}
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ }
+ ],
+ "snippets": [
+ {
+ "group": "Charts",
+ "label": {
+ "zh_CN": "图表"
+ },
+ "children": [
+ {
+ "name": {
+ "zh_CN": "折线图"
+ },
+ "icon": "line",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsLine",
+ "schema": {
+ "componentName": "TinyHuichartsLine",
+ "props": {
+ "options": {
+ "theme": "hdesign-light",
+ "padding": [
+ 50,
+ 30,
+ 50,
+ 20
+ ],
+ "legend": {
+ "show": true,
+ "icon": "line"
+ },
+ "data": [
+ {
+ "Month": "Jan",
+ "Domestics": 33,
+ "Abroad": 37
+ },
+ {
+ "Month": "Feb",
+ "Domestics": 27,
+ "Abroad": 39
+ },
+ {
+ "Month": "Mar",
+ "Domestics": 31,
+ "Abroad": 20
+ },
+ {
+ "Month": "Apr",
+ "Domestics": 30,
+ "Abroad": 15
+ },
+ {
+ "Month": "May",
+ "Domestics": 37,
+ "Abroad": 13
+ },
+ {
+ "Month": "Jun",
+ "Domestics": 36,
+ "Abroad": 17
+ },
+ {
+ "Month": "Jul",
+ "Domestics": 42,
+ "Abroad": 22
+ },
+ {
+ "Month": "Aug",
+ "Domestics": 22,
+ "Abroad": 12
+ },
+ {
+ "Month": "Sep",
+ "Domestics": 17,
+ "Abroad": 30
+ },
+ {
+ "Month": "Oct",
+ "Domestics": 40,
+ "Abroad": 33
+ },
+ {
+ "Month": "Nov",
+ "Domestics": 42,
+ "Abroad": 22
+ },
+ {
+ "Month": "Dec",
+ "Domestics": 32,
+ "Abroad": 11
+ }
+ ],
+ "xAxis": {
+ "data": "Month"
+ },
+ "yAxis": {
+ "name": "Percentage(%)"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "柱状图"
+ },
+ "icon": "histogram",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsHistogram",
+ "schema": {
+ "componentName": "TinyHuichartsHistogram",
+ "props": {
+ "options": {
+ "theme": "hdesign-light",
+ "padding": [
+ 50,
+ 30,
+ 50,
+ 20
+ ],
+ "data": [
+ {
+ "Month": "Jan",
+ "Domestic": 33,
+ "Abroad": 1
+ },
+ {
+ "Month": "Feb",
+ "Domestic": 27,
+ "Abroad": 39
+ },
+ {
+ "Month": "Mar",
+ "Domestic": 31,
+ "Abroad": 20
+ },
+ {
+ "Month": "Apr",
+ "Domestic": 30,
+ "Abroad": 15
+ },
+ {
+ "Month": "May",
+ "Domestic": 37,
+ "Abroad": 1
+ },
+ {
+ "Month": "Jun",
+ "Domestic": 36,
+ "Abroad": 17
+ },
+ {
+ "Month": "Jul",
+ "Domestic": 42,
+ "Abroad": 22
+ },
+ {
+ "Month": "Aug",
+ "Domestic": 22,
+ "Abroad": 12
+ },
+ {
+ "Month": "Sep",
+ "Domestic": 17,
+ "Abroad": 30
+ },
+ {
+ "Month": "Oct",
+ "Domestic": 40,
+ "Abroad": 33
+ },
+ {
+ "Month": "Nov",
+ "Domestic": 42,
+ "Abroad": 22
+ },
+ {
+ "Month": "Dec",
+ "Domestic": 32,
+ "Abroad": 1
+ }
+ ],
+ "xAxis": {
+ "data": "Month"
+ },
+ "yAxis": {
+ "name": "Percentage(%)"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "条形图"
+ },
+ "icon": "bar",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsBar",
+ "schema": {
+ "componentName": "TinyHuichartsBar",
+ "props": {
+ "options": {
+ "theme": "hdesign-light",
+ "padding": [
+ 50,
+ 30,
+ 50,
+ 20
+ ],
+ "data": [
+ {
+ "Month": "Jan",
+ "Domestic": 33,
+ "Abroad": 1
+ },
+ {
+ "Month": "Feb",
+ "Domestic": 27,
+ "Abroad": 39
+ },
+ {
+ "Month": "Mar",
+ "Domestic": 31,
+ "Abroad": 20
+ },
+ {
+ "Month": "Apr",
+ "Domestic": 30,
+ "Abroad": 15
+ },
+ {
+ "Month": "May",
+ "Domestic": 37,
+ "Abroad": 1
+ },
+ {
+ "Month": "Jun",
+ "Domestic": 36,
+ "Abroad": 17
+ },
+ {
+ "Month": "Jul",
+ "Domestic": 42,
+ "Abroad": 22
+ },
+ {
+ "Month": "Aug",
+ "Domestic": 22,
+ "Abroad": 12
+ },
+ {
+ "Month": "Sep",
+ "Domestic": 17,
+ "Abroad": 30
+ },
+ {
+ "Month": "Oct",
+ "Domestic": 40,
+ "Abroad": 33
+ },
+ {
+ "Month": "Nov",
+ "Domestic": 42,
+ "Abroad": 22
+ },
+ {
+ "Month": "Dec",
+ "Domestic": 32,
+ "Abroad": 1
+ }
+ ],
+ "xAxis": {
+ "data": "Month"
+ },
+ "yAxis": {
+ "name": "Percentage(%)"
+ },
+ "direction": "horizontal"
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "圆盘图"
+ },
+ "icon": "pie",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsPie",
+ "schema": {
+ "componentName": "TinyHuichartsPie",
+ "props": {
+ "options": {
+ "type": "pie",
+ "theme": "hdesign-light",
+ "label": {
+ "show": true,
+ "line": true,
+ "labelHtml": "{a|}{b|{b}:}{c|{d}%}",
+ "rich": {
+ "a": {
+ "width": 12,
+ "height": 12,
+ "backgroundColor": {
+ "image": "./image/charts/pie/ic_jiantou_hong.svg"
+ }
+ },
+ "b": {
+ "padding": [
+ 2,
+ 4,
+ 0,
+ 0
+ ]
+ },
+ "c": {
+ "fontWeight": "bold",
+ "padding": [
+ 2,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ }
+ },
+ "data": [
+ {
+ "value": 100,
+ "name": "VPC"
+ },
+ {
+ "value": 90,
+ "name": "IM"
+ },
+ {
+ "value": 49,
+ "name": "EIP"
+ },
+ {
+ "value": 14,
+ "name": "SG"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "环形图"
+ },
+ "icon": "ring",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsRing",
+ "schema": {
+ "componentName": "TinyHuichartsRing",
+ "props": {
+ "options": {
+ "theme": "hdesign-light",
+ "type": "circle",
+ "data": [
+ {
+ "value": 100,
+ "name": "VPC"
+ },
+ {
+ "value": 90,
+ "name": "IM"
+ },
+ {
+ "value": 49,
+ "name": "EIP"
+ },
+ {
+ "value": 14,
+ "name": "SG"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "雷达图"
+ },
+ "icon": "radar",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsRadar",
+ "schema": {
+ "componentName": "TinyHuichartsRadar",
+ "props": {
+ "options": {
+ "theme": "hdesign-light",
+ "legend": {
+ "show": true,
+ "position": {
+ "left": "center",
+ "bottom": 20.1
+ }
+ },
+ "radarMax": 100,
+ "data": {
+ "Domestic": {
+ "Equipment": 41,
+ "VM": 91,
+ "CSP": 81,
+ "RD": 51,
+ "Markets": 71
+ },
+ "Abroad": {
+ "Equipment": 72,
+ "VM": 55,
+ "CSP": 93,
+ "RD": 90,
+ "Markets": 82
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "瀑布图"
+ },
+ "icon": "waterfall",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsWaterfall",
+ "schema": {
+ "componentName": "TinyHuichartsWaterfall",
+ "props": {
+ "options": {
+ "padding": [
+ 50,
+ 30,
+ 20,
+ 20
+ ],
+ "legend": {
+ "show": false
+ },
+ "type": "water-fall",
+ "data": [
+ {
+ "Name": "NLE",
+ "User": 10
+ },
+ {
+ "Name": "HIN",
+ "User": 20
+ },
+ {
+ "Name": "FBP",
+ "User": 9
+ },
+ {
+ "Name": "VEDIO",
+ "User": 35
+ },
+ {
+ "Name": "SASS",
+ "User": 20
+ },
+ {
+ "Name": "RDS",
+ "User": 35
+ },
+ {
+ "Name": "E-SYS",
+ "User": 9
+ }
+ ],
+ "xAxis": {
+ "data": "Name"
+ },
+ "yAxis": {
+ "name": "Number"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "漏斗图"
+ },
+ "icon": "funnel",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsFunnel",
+ "schema": {
+ "componentName": "TinyHuichartsFunnel",
+ "props": {
+ "options": {
+ "data": [
+ {
+ "value": 100,
+ "name": "Show"
+ },
+ {
+ "value": 75,
+ "name": "Click"
+ },
+ {
+ "value": 50,
+ "name": "Visit"
+ },
+ {
+ "value": 25,
+ "name": "Order"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "散点图"
+ },
+ "icon": "scatter",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsScatter",
+ "schema": {
+ "componentName": "TinyHuichartsScatter",
+ "props": {
+ "options": {
+ "padding": [
+ 50,
+ 30,
+ 50,
+ 20
+ ],
+ "legend": {
+ "orient": "horizontal",
+ "show": true,
+ "position": {
+ "left": "center",
+ "bottom": 15
+ }
+ },
+ "bubbleSize": [
+ 20,
+ 100
+ ],
+ "xAxisType": "value",
+ "data": {
+ "1990": [
+ [
+ 28604,
+ 77,
+ 1709866,
+ "Australia",
+ 1990
+ ],
+ [
+ 31163,
+ 77.4,
+ 27662440,
+ "Canada",
+ 1990
+ ],
+ [
+ 60001,
+ 68,
+ 1154605773,
+ "China",
+ 1990
+ ],
+ [
+ 13670,
+ 74.7,
+ 10582082,
+ "Cuba",
+ 1990
+ ],
+ [
+ 28599,
+ 75,
+ 4986705,
+ "Finland",
+ 1990
+ ]
+ ],
+ "2000": [
+ [
+ 19349,
+ 69.6,
+ 147568552,
+ "Russia",
+ 2000
+ ],
+ [
+ 10670,
+ 67.3,
+ 53994606,
+ "Turkey",
+ 2000
+ ],
+ [
+ 26424,
+ 75.7,
+ 57110117,
+ "United Kingdom",
+ 2000
+ ],
+ [
+ 37062,
+ 75.4,
+ 252847810,
+ "United States",
+ 2000
+ ],
+ [
+ 23038,
+ 73.13,
+ 143456918,
+ "Russia",
+ 2000
+ ]
+ ],
+ "2015": [
+ [
+ 44056,
+ 81.8,
+ 23968976,
+ "Australia",
+ 2015
+ ],
+ [
+ 43294,
+ 81.7,
+ 35939927,
+ "Canada",
+ 2015
+ ],
+ [
+ 13334,
+ 76.9,
+ 1376048943,
+ "Cuba",
+ 2015
+ ],
+ [
+ 21291,
+ 78.5,
+ 11389566,
+ "Finland",
+ 2015
+ ],
+ [
+ 38923,
+ 80.8,
+ 5503457,
+ "France",
+ 2015
+ ]
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "仪表盘"
+ },
+ "icon": "gauge",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsGauge",
+ "schema": {
+ "componentName": "TinyHuichartsGauge",
+ "props": {
+ "options": {
+ "splitColor": [
+ [
+ 0.25,
+ "#0d9458"
+ ],
+ [
+ 0.5,
+ "#eeba18"
+ ],
+ [
+ 0.75,
+ "#ec6f1a"
+ ],
+ [
+ 1,
+ "#f43146"
+ ]
+ ],
+ "pointer": true,
+ "data": [
+ {
+ "value": 71,
+ "name": "Utilization rate"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "拓扑图"
+ },
+ "icon": "graph",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsGraph",
+ "schema": {
+ "componentName": "TinyHuichartsGraph",
+ "props": {
+ "options": {
+ "animationDurationUpdate": 1600,
+ "animationEasingUpdate": "quinticInOut",
+ "series": [
+ {
+ "type": "graph",
+ "layout": "none",
+ "symbolSize": 48,
+ "color": "#42A5F5",
+ "roam": true,
+ "label": {
+ "normal": {
+ "show": true
+ }
+ },
+ "edgeSymbol": [
+ "circle",
+ "arrow"
+ ],
+ "edgeSymbolSize": [
+ 3,
+ 10
+ ],
+ "edgeLabel": {
+ "normal": {
+ "textStyle": {
+ "fontSize": 18
+ }
+ }
+ },
+ "data": [
+ {
+ "name": "节点 1",
+ "x": 300,
+ "y": 300
+ },
+ {
+ "name": "节点 2",
+ "x": 800,
+ "y": 300
+ },
+ {
+ "name": "节点 3",
+ "x": 550,
+ "y": 100
+ },
+ {
+ "name": "节点 4",
+ "x": 550,
+ "y": 500
+ }
+ ],
+ "links": [
+ {
+ "source": 0,
+ "target": 1,
+ "symbolSize": [
+ 5,
+ 20
+ ],
+ "label": {
+ "normal": {
+ "show": true
+ }
+ },
+ "lineStyle": {
+ "normal": {
+ "width": 5,
+ "curveness": 0.2
+ }
+ }
+ },
+ {
+ "source": "节点 2",
+ "target": "节点 1",
+ "label": {
+ "normal": {
+ "show": true
+ }
+ },
+ "lineStyle": {
+ "normal": {
+ "curveness": 0.2
+ }
+ }
+ },
+ {
+ "source": "节点 1",
+ "target": "节点 3"
+ },
+ {
+ "source": "节点 2",
+ "target": "节点 3"
+ },
+ {
+ "source": "节点 2",
+ "target": "节点 4"
+ },
+ {
+ "source": "节点 1",
+ "target": "节点 4"
+ }
+ ],
+ "lineStyle": {
+ "normal": {
+ "opacity": 0.9,
+ "width": 2,
+ "curveness": 0
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "进度图"
+ },
+ "icon": "process",
+ "screenshot": "",
+ "snippetName": "TinyHuichartsProcess",
+ "schema": {
+ "componentName": "TinyHuichartsProcess",
+ "props": {
+ "options": {
+ "name": "ProcessBarChart",
+ "theme": "light",
+ "padding": [
+ 32,
+ 32,
+ 0,
+ 32
+ ],
+ "color": [
+ "#fa2a2d",
+ "#ff7500",
+ "#ffbf00",
+ "#41ba41",
+ "#00aaee"
+ ],
+ "data": [
+ {
+ "name": "UniEPMgr",
+ "value": 80
+ },
+ {
+ "name": "SMLoglic",
+ "value": 65
+ },
+ {
+ "name": "SSO",
+ "value": 45
+ },
+ {
+ "name": "APIMgr",
+ "value": 20
+ },
+ {
+ "name": "Logtransfer",
+ "value": 12
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/packages/materials/vue-opentiny-vue/src/meta/materials/extend.json b/packages/materials/vue-opentiny-vue/src/meta/materials/extend.json
new file mode 100644
index 00000000..4416221e
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/materials/extend.json
@@ -0,0 +1,150 @@
+{
+ "data": {
+ "framework": "Vue",
+ "materials": {
+ "components": [
+ {
+ "name": {
+ "zh_CN": "看板画布"
+ },
+ "component": "GridStack",
+ "description": "看板画布,可完成对看板瓷砖的布局",
+ "group": "component",
+ "schema": {
+ "properties": [],
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "自定义看板内容"
+ },
+ "description": {
+ "zh_CN": "看板画布的内容,通常为看板瓷砖列表"
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "看板瓷砖组件"
+ },
+ "description": "看板瓷砖,包裹展示内容,生成看板所需参数,看板在画布中完成布局,画布整体由12 * 12个格子排列,举例:看板占据2行2列,参数各项取值为[{x: 0, y: 0, w: 2, h: 2}]",
+ "component": "GridStackItem",
+ "group": "component",
+ "schema": {
+ "properties": [
+ {
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "property": "x",
+ "label": {
+ "text": {
+ "zh_CN": "整体布局中横坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
+ }
+ },
+ "description": {
+ "zh_CN": "整体布局中横坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "type": "number"
+ },
+ {
+ "property": "y",
+ "label": {
+ "text": {
+ "zh_CN": "整体布局中纵坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
+ }
+ },
+ "description": {
+ "zh_CN": "整体布局中纵坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "type": "number"
+ },
+ {
+ "property": "w",
+ "label": {
+ "text": {
+ "zh_CN": "看板在画布中占据的列数,画布总共12列,即该数值取值范围为0到11"
+ }
+ },
+ "description": {
+ "zh_CN": "看板在画布中占据的列数,画布总共12列,即该数值取值范围为0到11"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "type": "number"
+ },
+ {
+ "property": "h",
+ "label": {
+ "text": {
+ "zh_CN": "看板在画布中占据的行数,画布总共12行,即该数值取值范围为0到11"
+ }
+ },
+ "description": {
+ "zh_CN": "看板在画布中占据的行数,画布总共12行,即该数值取值范围为0到11"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "type": "number"
+ },
+ {
+ "property": "id",
+ "label": {
+ "text": {
+ "zh_CN": "唯一标识"
+ }
+ },
+ "description": {
+ "zh_CN": "唯一标识,要保证唯一性"
+ },
+ "required": true,
+ "readOnly": false,
+ "disabled": false,
+ "type": "string"
+ },
+ {
+ "property": "autoPosition",
+ "label": {
+ "text": {
+ "zh_CN": "是否开启自动在画布中定位"
+ }
+ },
+ "description": {
+ "zh_CN": "是否开启自动在画布中定位"
+ },
+ "required": false,
+ "readOnly": false,
+ "disabled": false,
+ "type": "boolean"
+ }
+ ]
+ }
+ ],
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "自定义看板瓷砖内容"
+ },
+ "description": {
+ "zh_CN": "可以使用其他组件作为瓷砖内容,也可以自定义实现"
+ }
+ }
+ }
+ }
+ }
+ ],
+ "snippets": []
+ }
+ }
+}
diff --git a/packages/materials/vue-opentiny-vue/src/meta/meta.ts b/packages/materials/vue-opentiny-vue/src/meta/meta.ts
new file mode 100644
index 00000000..7023522f
--- /dev/null
+++ b/packages/materials/vue-opentiny-vue/src/meta/meta.ts
@@ -0,0 +1,36 @@
+import type { IMaterialsMeta, IExample, IMaterialsProtocol } from '@opentiny/genui-sdk-core';
+import bundleJson from './materials/bundle.json' with { type: 'json' };
+import builtinJson from './materials/builtin.json' with { type: 'json' };
+import chartJson from './materials/chart.json' with { type: 'json' };
+import extendJson from './materials/extend.json' with { type: 'json' };
+import { examples as allExamples } from './example-schema';
+import { miniWhiteList, standardWhiteList } from './white-list';
+
+// TODO: 优化物料协议后,删除 as IMaterialsProtocol[]
+const baseMetaMaterials = [bundleJson, builtinJson, extendJson] as IMaterialsProtocol[];
+
+const standardMetaMaterials = [chartJson, ...baseMetaMaterials] as IMaterialsProtocol[];
+
+const STANDARD_RULES = [
+ '禁止设置饼图的 `settings.radius`',
+];
+
+function filterExamples(ids: string[]) {
+ return allExamples.filter((example): example is IExample => !!example.id && ids.includes(example.id));
+}
+
+export const materialsMeta: IMaterialsMeta = {
+ materials: standardMetaMaterials,
+ wrapperComponent: 'TinyCard',
+ whiteList: standardWhiteList,
+ examples: filterExamples(['form', 'info', 'grid', 'tabs']),
+ rules: STANDARD_RULES,
+};
+
+export const miniMaterialsMeta: IMaterialsMeta = {
+ materials: baseMetaMaterials,
+ wrapperComponent: 'TinyCard',
+ whiteList: miniWhiteList,
+ examples: filterExamples(['form', 'grid']),
+ rules: [],
+};
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/white-list.ts b/packages/materials/vue-opentiny-vue/src/meta/white-list.ts
similarity index 60%
rename from packages/materials/vue-opentiny-vue/src/render-config/white-list.ts
rename to packages/materials/vue-opentiny-vue/src/meta/white-list.ts
index 24d6888c..3eae4946 100644
--- a/packages/materials/vue-opentiny-vue/src/render-config/white-list.ts
+++ b/packages/materials/vue-opentiny-vue/src/meta/white-list.ts
@@ -1,13 +1,4 @@
-export const whiteList = [
- // 'ElInput',
- // 'ElDatePicker',
- // 'ElButton',
- // 'ElForm',
- // 'ElFormItem',
- // 'ElTable',
- // 'ElTableColumn',
- 'TinyCarouselItem',
- 'TinyCarousel',
+export const miniWhiteList = [
'a',
'h1',
'h2',
@@ -19,64 +10,66 @@ export const whiteList = [
'ol',
'ul',
'li',
+ 'div',
'input',
'video',
- 'Img',
- // 'button',
- // 'table',
- // 'td',
- // 'form',
'label',
- // 'TinyButtonGroup',
- 'TinyRow',
- 'TinyLayout',
+ 'Img',
+ 'Slot',
+ 'Text',
'TinyForm',
'TinyFormItem',
- 'TinyCol',
'TinyButton',
'TinyInput',
'TinyRadio',
'TinyRadioGroup',
'TinySelect',
'TinySwitch',
- 'TinySearch',
+ 'TinyNumeric',
'TinyCheckbox',
'TinyCheckboxButton',
'TinyCheckboxGroup',
- // 'TinyDialogBox',
- 'TinyTabs',
- 'TinyTabItem',
- // 'ActionButton',
- // 'TinyBreadcrumb',
- // 'TinyBreadcrumbItem',
- // 'TinyCollapse',
- // 'TinyCollapseItem',
+ 'TinyDatePicker',
'TinyGrid',
'TinyCard',
- // 'TinyGridColumn',
- // 'TinyPager',
- // 'TinyPopeditor',
+];
+
+export const standardWhiteList = [
+ ...miniWhiteList,
+ 'TinyPager',
+ 'TinyHuichartsLine',
+ 'TinyHuichartsHistogram',
+ 'TinyHuichartsBar',
+ 'TinyHuichartsRadar',
+ 'TinyHuichartsRing',
+ 'TinyHuichartsPie',
+ 'TinyHuichartsFunnel',
+ 'TinyHuichartsScatter',
+ 'TinyHuichartsWaterfall',
+ 'TinyHuichartsGauge',
+ 'TinyHuichartsGraph',
+ 'TinyHuichartsProcess',
+];
+
+// TODO: plus物料和白名单袋完善
+export const plusWhiteList = [
+ ...standardWhiteList,
+ 'TinyCarouselItem',
+ 'TinyCarousel',
'TinyTree',
- // 'TinyTimeLine',
- // 'TinyTooltip',
- // 'TinyPopover',
- 'TinyDatePicker',
- 'TinyNumeric',
'TinyTransfer',
- 'div',
- 'Slot',
+ // 'GridStack',
+ // 'GridStackItem'
// 'RouterView',
// 'RouterLink',
// 'Collection',
- 'Text',
- 'Icon',
- 'Img',
- 'TinyChartPie',
- 'TinyChartLine',
- 'TinyChartHistogram',
- 'TinyChartBar',
- 'TinyChartRadar',
- 'TinyChartRing',
- // 'GridStack',
- // 'GridStackItem'
+ // 'TinyBreadcrumb',
+ // 'TinyBreadcrumbItem',
+ // 'TinyCollapse',
+ // 'TinyCollapseItem',
+ // 'TinyTimeLine',
+ // 'TinyTooltip',
+ // 'TinyPopover',
+ // 'TinyDialogBox',
+ // 'TinyPopeditor',
];
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/chart.json b/packages/materials/vue-opentiny-vue/src/render-config/chart.json
deleted file mode 100644
index 212a54fd..00000000
--- a/packages/materials/vue-opentiny-vue/src/render-config/chart.json
+++ /dev/null
@@ -1,1785 +0,0 @@
-{
- "data": {
- "framework": "Vue",
- "materials": {
- "components": [
- {
- "name": {
- "zh_CN": "饼图"
- },
- "component": "TinyChartPie",
- "icon": "pie",
- "description": "基于 eCharts 封装的折线图",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "@opentiny/vue",
- "exportName": "ChartPie",
- "version": "3.14.0",
- "destructuring": true,
- "script": "https://unpkg.com/@opentiny/vue@~3.14/runtime/tiny-vue.mjs",
- "css": "https://unpkg.com/@opentiny/vue-theme@~3.14/index.css"
- },
- "group": "component",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": [
- ""
- ]
- },
- "contextMenu": {
- "actions": [
- "copy",
- "remove",
- "insert",
- "updateAttr",
- "bindEevent",
- "createBlock"
- ],
- "disable": [
- ]
- },
- "invalidity": [
- ""
- ],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "图表数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "settings",
- "label": {
- "text": {
- "zh_CN": "图表配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "width",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的宽度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "height",
- "label": {
- "text": {
- "zh_CN": "图表容器的高度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "type": "string",
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "extend",
- "label": {
- "text": {
- "zh_CN": "图表扩展配置,参考eCharts"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "events",
- "label": {
- "text": {
- "zh_CN": "事件绑定"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "显示loading"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "data-empty",
- "label": {
- "text": {
- "zh_CN": "暂无数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": [
- ]
- }
- },
- {
- "name": {
- "zh_CN": "折线图"
- },
- "component": "TinyChartLine",
- "icon": "line",
- "description": "基于 eCharts 封装的折线图",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "@opentiny/vue",
- "exportName": "ChartLine",
- "version": "3.14.0",
- "destructuring": true,
- "script": "https://unpkg.com/@opentiny/vue@~3.14/runtime/tiny-vue.mjs",
- "css": "https://unpkg.com/@opentiny/vue-theme@~3.14/index.css"
- },
- "group": "component",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": [
- ""
- ]
- },
- "contextMenu": {
- "actions": [
- "copy",
- "remove",
- "insert",
- "updateAttr",
- "bindEevent",
- "createBlock"
- ],
- "disable": [
- ]
- },
- "invalidity": [
- ""
- ],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "图表数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "settings",
- "label": {
- "text": {
- "zh_CN": "图表配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "events",
- "label": {
- "text": {
- "zh_CN": "事件绑定"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "extend",
- "label": {
- "text": {
- "zh_CN": "图表扩展配置,参考eCharts"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "height",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的高度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "width",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的宽度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "显示loading"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "data-empty",
- "label": {
- "text": {
- "zh_CN": "暂无数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": [
- ]
- }
- },
- {
- "name": {
- "zh_CN": "柱状图"
- },
- "component": "TinyChartHistogram",
- "icon": "histogram ",
- "description": "基于 eCharts 封装的柱状图",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "@opentiny/vue",
- "exportName": "ChartHistogram",
- "version": "3.14.0",
- "destructuring": true,
- "script": "https://unpkg.com/@opentiny/vue@~3.14/runtime/tiny-vue.mjs",
- "css": "https://unpkg.com/@opentiny/vue-theme@~3.14/index.css"
- },
- "group": "component",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": [
- ""
- ]
- },
- "contextMenu": {
- "actions": [
- "copy",
- "remove",
- "insert",
- "updateAttr",
- "bindEevent",
- "createBlock"
- ],
- "disable": [
- ]
- },
- "invalidity": [
- ""
- ],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "图表数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "settings",
- "label": {
- "text": {
- "zh_CN": "图表配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "extend",
- "label": {
- "text": {
- "zh_CN": "图表扩展配置,参考eChart"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "height",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的高度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "width",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的宽度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "events",
- "label": {
- "text": {
- "zh_CN": "事件绑定"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "显示loading"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "data-empty",
- "label": {
- "text": {
- "zh_CN": "暂无数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": [
- ]
- }
- },
- {
- "name": {
- "zh_CN": "条形图"
- },
- "component": "TinyChartBar",
- "icon": "bar",
- "description": "基于 eCharts 封装的条形图",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "@opentiny/vue",
- "exportName": "ChartBar",
- "version": "3.14.0",
- "destructuring": true,
- "script": "https://unpkg.com/@opentiny/vue@~3.14/runtime/tiny-vue.mjs",
- "css": "https://unpkg.com/@opentiny/vue-theme@~3.14/index.css"
- },
- "group": "component",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": [
- ""
- ]
- },
- "contextMenu": {
- "actions": [
- "copy",
- "remove",
- "insert",
- "updateAttr",
- "bindEevent",
- "createBlock"
- ],
- "disable": [
- ]
- },
- "invalidity": [
- ""
- ],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "图表数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "settings",
- "label": {
- "text": {
- "zh_CN": "图表配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "events",
- "label": {
- "text": {
- "zh_CN": "事件绑定"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "extend",
- "label": {
- "text": {
- "zh_CN": "图表扩展配置,参考eCharts"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "height",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的高度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "width",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的宽度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "显示loading"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "data-empty",
- "label": {
- "text": {
- "zh_CN": "暂无数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": [
- ]
- }
- },
- {
- "name": {
- "zh_CN": "雷达图"
- },
- "component": "TinyChartRadar",
- "icon": "radar",
- "description": "基于 eCharts 封装的雷达图",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "@opentiny/vue",
- "exportName": "ChartRadar",
- "version": "3.14.0",
- "destructuring": true,
- "script": "https://unpkg.com/@opentiny/vue@~3.14/runtime/tiny-vue.mjs",
- "css": "https://unpkg.com/@opentiny/vue-theme@~3.14/index.css"
- },
- "group": "component",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": [
- ""
- ]
- },
- "contextMenu": {
- "actions": [
- "copy",
- "remove",
- "insert",
- "updateAttr",
- "bindEevent",
- "createBlock"
- ],
- "disable": [
- ]
- },
- "invalidity": [
- ""
- ],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "图表数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "settings",
- "label": {
- "text": {
- "zh_CN": "图表配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "width",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的宽度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "height",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的高度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "extend",
- "label": {
- "text": {
- "zh_CN": "图表扩展配置,参考eCharts"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "events",
- "label": {
- "text": {
- "zh_CN": "事件绑定"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "显示loading"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "data-empty",
- "label": {
- "text": {
- "zh_CN": "暂无数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": [
- ]
- }
- },
- {
- "name": {
- "zh_CN": "环图"
- },
- "component": "TinyChartRing",
- "icon": "ring",
- "description": "基于 eCharts 封装的环图",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- "package": "@opentiny/vue",
- "exportName": "ChartRing",
- "version": "3.14.0",
- "destructuring": true,
- "script": "https://unpkg.com/@opentiny/vue@~3.14/runtime/tiny-vue.mjs",
- "css": "https://unpkg.com/@opentiny/vue-theme@~3.14/index.css"
- },
- "group": "component",
- "configure": {
- "loop": true,
- "condition": true,
- "styles": true,
- "isContainer": false,
- "isModal": false,
- "isPopper": false,
- "nestingRule": {
- "childWhitelist": "",
- "parentWhitelist": "",
- "descendantBlacklist": "",
- "ancestorWhitelist": ""
- },
- "isNullNode": false,
- "isLayout": false,
- "rootSelector": "",
- "shortcuts": {
- "properties": [
- ""
- ]
- },
- "contextMenu": {
- "actions": [
- "copy",
- "remove",
- "insert",
- "updateAttr",
- "bindEevent",
- "createBlock"
- ],
- "disable": [
- ]
- },
- "invalidity": [
- ""
- ],
- "clickCapture": true,
- "framework": "Vue"
- },
- "schema": {
- "properties": [
- {
- "name": "0",
- "label": {
- "zh_CN": "基础信息"
- },
- "content": [
- {
- "property": "data",
- "label": {
- "text": {
- "zh_CN": "图表数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "settings",
- "label": {
- "text": {
- "zh_CN": "图表配置"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "width",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的宽度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "height",
- "type": "string",
- "label": {
- "text": {
- "zh_CN": "图表容器的高度,支持px、%、em等单位, 需要包含单位"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "InputConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "extend",
- "label": {
- "text": {
- "zh_CN": "图表扩展配置,参考eCharts"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "events",
- "label": {
- "text": {
- "zh_CN": "事件绑定"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CodeConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "loading",
- "label": {
- "text": {
- "zh_CN": "显示loading"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- },
- {
- "property": "data-empty",
- "label": {
- "text": {
- "zh_CN": "暂无数据"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SwitchConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "description": {
- "zh_CN": ""
- }
- }
- ],
- "events": [
- ]
- }
- }
- ],
- "snippets": [
- {
- "group": "Charts",
- "label": {
- "zh_CN": "图表"
- },
- "children": [
- {
- "name": {
- "zh_CN": "饼图"
- },
- "icon": "pie",
- "screenshot": "",
- "snippetName": "TinyChartPie",
- "schema": {
- "componentName": "TinyChartPie",
- "props": {
- "data": {
- "columns": [
- "日期",
- "访问用户"
- ],
- "rows": [
- {
- "日期": "1/1",
- "访问用户": 1393
- },
- {
- "日期": "1/2",
- "访问用户": 3530
- },
- {
- "日期": "1/3",
- "访问用户": 2923
- },
- {
- "日期": "1/4",
- "访问用户": 1723
- },
- {
- "日期": "1/5",
- "访问用户": 3792
- },
- {
- "日期": "1/6",
- "访问用户": 4593
- }
- ]
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "折线图"
- },
- "icon": "line",
- "screenshot": "",
- "snippetName": "TinyChartLine",
- "schema": {
- "componentName": "TinyChartLine",
- "props": {
- "data": {
- "columns": [
- "日期",
- "访问用户",
- "下单用户",
- "下单率"
- ],
- "rows": [
- {
- "日期": "1/1",
- "访问用户": 1393,
- "下单用户": 1093,
- "下单率": 0.32
- },
- {
- "日期": "1/2",
- "访问用户": 3530,
- "下单用户": 3230,
- "下单率": 0.26
- },
- {
- "日期": "1/3",
- "访问用户": 2923,
- "下单用户": 2623,
- "下单率": 0.76
- },
- {
- "日期": "1/4",
- "访问用户": 1723,
- "下单用户": 1423,
- "下单率": 0.49
- },
- {
- "日期": "1/5",
- "访问用户": 3792,
- "下单用户": 3492,
- "下单率": 0.323
- },
- {
- "日期": "1/6",
- "访问用户": 4593,
- "下单用户": 4293,
- "下单率": 0.78
- }
- ]
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "柱状图"
- },
- "icon": "histogram ",
- "screenshot": "",
- "snippetName": "TinyChartHistogram",
- "schema": {
- "componentName": "TinyChartHistogram",
- "props": {
- "data": {
- "columns": [
- "日期",
- "访问用户",
- "下单用户",
- "下单率"
- ],
- "rows": [
- {
- "日期": "1/1",
- "访问用户": 1393,
- "下单用户": 1093,
- "下单率": 0.32
- },
- {
- "日期": "1/2",
- "访问用户": 3530,
- "下单用户": 3230,
- "下单率": 0.26
- },
- {
- "日期": "1/3",
- "访问用户": 2923,
- "下单用户": 2623,
- "下单率": 0.76
- },
- {
- "日期": "1/4",
- "访问用户": 1723,
- "下单用户": 1423,
- "下单率": 0.49
- },
- {
- "日期": "1/5",
- "访问用户": 3792,
- "下单用户": 3492,
- "下单率": 0.323
- },
- {
- "日期": "1/6",
- "访问用户": 4593,
- "下单用户": 4293,
- "下单率": 0.78
- }
- ]
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "条形图"
- },
- "icon": "bar",
- "screenshot": "",
- "snippetName": "TinyChartBar",
- "schema": {
- "componentName": "TinyChartBar",
- "props": {
- "data": {
- "columns": [
- "日期",
- "访问用户",
- "下单用户",
- "下单率"
- ],
- "rows": [
- {
- "日期": "1/1",
- "访问用户": 1393,
- "下单用户": 1093,
- "下单率": 0.32
- },
- {
- "日期": "1/2",
- "访问用户": 3530,
- "下单用户": 3230,
- "下单率": 0.26
- },
- {
- "日期": "1/3",
- "访问用户": 2923,
- "下单用户": 2623,
- "下单率": 0.76
- },
- {
- "日期": "1/4",
- "访问用户": 1723,
- "下单用户": 1423,
- "下单率": 0.49
- },
- {
- "日期": "1/5",
- "访问用户": 3792,
- "下单用户": 3492,
- "下单率": 0.323
- },
- {
- "日期": "1/6",
- "访问用户": 4593,
- "下单用户": 4293,
- "下单率": 0.78
- }
- ]
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "雷达图"
- },
- "icon": "radar",
- "screenshot": "",
- "snippetName": "TinyChartRadar",
- "schema": {
- "componentName": "TinyChartRadar",
- "props": {
- "data": {
- "columns": [
- "日期",
- "访问用户",
- "下单用户",
- "下单率"
- ],
- "rows": [
- {
- "日期": "1/1",
- "访问用户": 1393,
- "下单用户": 1093,
- "下单率": 0.32
- },
- {
- "日期": "1/2",
- "访问用户": 3530,
- "下单用户": 3230,
- "下单率": 0.26
- },
- {
- "日期": "1/3",
- "访问用户": 2923,
- "下单用户": 2623,
- "下单率": 0.76
- },
- {
- "日期": "1/4",
- "访问用户": 1723,
- "下单用户": 1423,
- "下单率": 0.49
- },
- {
- "日期": "1/5",
- "访问用户": 3792,
- "下单用户": 3492,
- "下单率": 0.323
- },
- {
- "日期": "1/6",
- "访问用户": 4593,
- "下单用户": 4293,
- "下单率": 0.78
- }
- ]
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "环图"
- },
- "icon": "ring",
- "screenshot": "",
- "snippetName": "TinyChartRing",
- "schema": {
- "componentName": "TinyChartRing",
- "props": {
- "data": {
- "columns": [
- "日期",
- "访问用户"
- ],
- "rows": [
- {
- "日期": "1/1",
- "访问用户": 1393
- },
- {
- "日期": "1/2",
- "访问用户": 3530
- },
- {
- "日期": "1/3",
- "访问用户": 2923
- },
- {
- "日期": "1/4",
- "访问用户": 1723
- },
- {
- "日期": "1/5",
- "访问用户": 3792
- },
- {
- "日期": "1/6",
- "访问用户": 4593
- }
- ]
- }
- }
- }
- }
- ]
- }
- ]
- }
- }
-}
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/example-schema.ts b/packages/materials/vue-opentiny-vue/src/render-config/example-schema.ts
deleted file mode 100644
index c317a0c8..00000000
--- a/packages/materials/vue-opentiny-vue/src/render-config/example-schema.ts
+++ /dev/null
@@ -1,835 +0,0 @@
-export const formSchema = {
- 'state': {
- 'formData': {
- 'name': '张三',
- 'sex': '男',
- 'department': 'HR',
- 'protocolStart': '2023-01-01',
- 'email': '',
- },
- },
- 'methods': {
- 'departChange': {
- 'type': 'JSFunction',
- 'value': 'function departChange(value) { console.log(value) }',
- },
- },
- 'componentName': 'Page',
- 'props': {
- 'style': 'width: 414px;',
- },
- 'children': [
- {
- 'componentName': 'h3',
- 'props': {},
- 'children': '更新员工信息',
- },
- {
- 'componentName': 'TinyForm',
- 'props': {
- 'model': {
- 'type': 'JSExpression',
- 'value': 'this.state.formData',
- },
- 'labelPosition': 'top',
- },
- 'children': [
- {
- 'componentName': 'TinyFormItem',
- 'props': {
- 'label': '姓名',
- 'prop': 'name',
- 'required': true,
- },
- 'children': [
- {
- 'componentName': 'TinyInput',
- 'props': {
- 'placeholder': '请输入',
- 'modelValue': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.name',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'TinyFormItem',
- 'props': {
- 'label': '工号',
- 'prop': 'id',
- 'required': true,
- },
- 'children': [
- {
- 'componentName': 'TinyInput',
- 'props': {
- 'disabled': true,
- 'modelValue': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.id',
- },
- 'onChange': {
- 'type': 'JSFunction',
- 'value': 'fucntion() { console.log(this.state.formData) }',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'TinyFormItem',
- 'props': {
- 'label': '性别',
- 'prop': 'sex',
- },
- 'children': [
- {
- 'componentName': 'TinyRadioGroup',
- 'props': {
- 'options': [
- {
- 'text': '男',
- 'label': '男',
- },
- {
- 'text': '女',
- 'label': '女',
- },
- ],
- 'modelValue': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.sex',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'TinyFormItem',
- 'props': {
- 'label': '部门',
- 'prop': 'depart',
- 'required': true,
- },
- 'children': [
- {
- 'componentName': 'TinySelect',
- 'props': {
- 'placeholder': '请选择',
- 'modelValue': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.depart',
- },
- 'options': [
- {
- 'value': 'HR',
- 'label': '人事部',
- },
- {
- 'value': 'other',
- 'label': '其他部门',
- },
- ],
- 'onChange': {
- 'type': 'JSExpression',
- 'value': 'this.departChange',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'TinyFormItem',
- 'props': {
- 'label': '入职日期',
- 'prop': 'date',
- },
- 'children': [
- {
- 'componentName': 'TinyDatePicker',
- 'props': {
- 'placeholder': '请输入',
- 'disabled': true,
- 'modelValue': {
- 'type': 'JSExpression',
- 'model': true,
- 'value': 'this.state.formData.date',
- },
- },
- },
- ],
- },
- {
- 'componentName': 'TinyFormItem',
- 'props': {
- 'label': '',
- },
- 'children': [
- {
- 'componentName': 'TinyButton',
- 'props': {
- 'text': '确认',
- },
- },
- ],
- },
- ],
- },
- ],
-};
-
-export const infoCardSchema = {
- 'componentName': 'Page',
- 'children': [
- {
- 'componentName': 'Text',
- 'props': {
- 'style': 'font-size: 14px;font-weight: bold;line-height:2;margin-bottom:20px;display:block;',
- 'text': '员工信息详情',
- },
- },
- {
- 'componentName': 'div',
- 'props': {
- 'className': 'component-base-style',
- 'style': 'width: 374px; background: #f5f5f5;border-radius: 12px;line-height:2;font-size:14px;padding: 20px 0;',
- },
- 'children': [
- {
- 'componentName': 'TinyLayout',
- 'props': { 'className': 'component-base-style' },
- 'children': [
- {
- 'componentName': 'TinyRow',
- 'children': [
- {
- 'componentName': 'TinyCol',
- 'props': { 'span': 3 },
- 'children': [{ 'componentName': 'Text', 'props': { 'text': '姓名' } }],
- },
- {
- 'componentName': 'TinyCol',
- 'props': { 'span': 9 },
- 'children': [{ 'componentName': 'Text', 'props': { 'text': '张三' } }],
- },
- ],
- },
- {
- 'componentName': 'TinyRow',
- 'children': [
- {
- 'componentName': 'TinyCol',
- 'props': { 'span': 3 },
- 'children': [{ 'componentName': 'Text', 'props': { 'text': '电话' } }],
- },
- {
- 'componentName': 'TinyCol',
- 'props': { 'span': 9 },
- 'children': [
- {
- 'componentName': 'Text',
- 'props': { 'text': '18856254558' },
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- 'id': 'body',
-};
-
-export const gridSchema = {
- 'componentName': 'Page',
- 'css':
- '.page-base-style {padding: 24px;background: #FFFFFF;}.block-base-style {margin: 16px;}.component-base-style {margin: 8px;}',
- 'props': { 'className': 'page-base-style' },
- 'lifeCycles': {},
- 'children': [
- {
- 'componentName': 'TinyGrid',
- 'props': {
- 'columns': [
- { 'type': 'index', 'width': 60 },
- { 'field': 'name', 'title': '姓名' },
- { 'field': 'id', 'title': '工号' },
- { 'field': 'sex', 'title': '性别' },
- { 'field': 'department', 'title': '部门' },
- { 'field': 'protocolStart', 'title': '入职日期' },
- { 'field': 'email', 'title': '邮箱' },
- {
- 'title': '操作',
- 'slots': {
- 'default': {
- 'type': 'JSSlot',
- 'value': [
- {
- 'componentName': 'div',
- 'id': '23324161',
- 'children': [
- {
- 'componentName': 'TinyButton',
- 'props': {
- 'className': 'component-base-style',
- 'text': {
- 'type': 'JSExpression',
- 'value': '`编辑${row.name}`',
- },
- },
- 'children': [],
- 'id': '24392624',
- },
- ],
- },
- ],
- 'params': [
- 'row',
- ],
- },
- },
- },
- ],
- 'data': [
- {
- 'name': '李四',
- 'id': '2',
- 'sex': '女',
- 'department': '技术部',
- 'protocolStart': '2019-05-15',
- 'email': 'lisi@test.com',
- },
- ],
- 'className': 'component-base-style',
- },
- },
- ],
- 'dataSource': { 'list': [] },
- 'id': 'body',
-};
-
-export const tabsSchema = {
- 'componentName': 'Page',
- 'fileName': 'Untitleda',
- 'css':
- '.page-base-style {\n padding: 24px;background: #FFFFFF;\n}\n\n.block-base-style {\n margin: 16px;\n}\n\n.component-base-style {\n margin: 8px;\n}\n',
- 'props': {
- 'className': 'page-base-style',
- },
- 'lifeCycles': {},
- 'children': [
- {
- 'componentName': 'CanvasFlexBox',
- 'id': 'e9a7b6c5',
- 'props': {
- 'flexDirection': 'column',
- 'justifyContent': 'center',
- 'alignItems': 'center',
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'id': 'f2g3h4i5',
- 'props': {
- 'text': '降本增效,加速企业数字化转型',
- 'style': 'font-size: 24px; font-weight: bold; margin-bottom: 20px;',
- },
- },
- {
- 'componentName': 'TinyTabs',
- 'id': 'j6k7l8m9',
- 'props': {
- 'modelValue': '精选推荐',
- 'className': 'component-base-style',
- },
- 'children': [
- {
- 'componentName': 'TinyTabItem',
- 'id': 'n0o1p2q3',
- 'props': {
- 'title': '精选推荐',
- 'name': '精选推荐',
- },
- 'children': [
- {
- 'componentName': 'CanvasFlexBox',
- 'id': 'r4s5t6u7',
- 'props': {
- 'flexDirection': 'row',
- 'justifyContent': 'space-around',
- 'alignItems': 'center',
- 'wrap': 'wrap',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'id': 'v8w9x0y1',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'z2a3b4c5',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/Domains.png',
- 'alt': '域名注册服务',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'd6e7f8g9',
- 'props': {
- 'text': '域名注册服务',
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'h0i1j2k3',
- 'props': {
- 'text': '适用于网站建设、域名投资等场景',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'l4m5n6o7',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'p8q9r0s1',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/mail0918.png',
- 'alt': '华为云企业邮箱',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 't2u3v4w5',
- 'props': {
- 'text': '华为云企业邮箱',
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'x6y7z8a9',
- 'props': {
- 'text': '免费试用,无限容量,全球畅邮',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'b0c1d2e3',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'f4g5h6i7',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/BusinessApplications/Cloudsite.png',
- 'alt': '企业门户(原云速建站)',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'j8k9l0m1',
- 'props': {
- 'text': '企业门户(原云速建站)',
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'n2o3p4q5',
- 'props': {
- 'text': '无需代码,一键拖拽,3000+模板随心选',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'r6s7t8u9',
- 'props': {
- 'style':
- 'width: 25%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'img',
- 'id': 'v0w1x2y3',
- 'props': {
- 'src':
- 'https://res-static.hc-cdn.cn/cloudbu-site/china/zh-cn/yunying/new-home/markplace/home_icon_14.svg',
- 'alt': '财税卫士',
- 'style': 'width: 60px; height: 60px; margin-bottom: 10px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'z4a5b6c7',
- 'props': {
- 'text': '财税卫士',
- 'style': 'font-size: 16px; font-weight: bold; margin-bottom: 5px;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'd8e9f0g1',
- 'props': {
- 'text': '智能财税风控检测软件,助力企业合规',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'TinyTabItem',
- 'id': 'h2i3j4k5',
- 'props': {
- 'title': '企业初创',
- 'name': '企业初创',
- },
- 'children': [],
- },
- {
- 'componentName': 'TinyTabItem',
- 'id': 'l6m7n8o9',
- 'props': {
- 'title': '企业营销',
- 'name': '企业营销',
- },
- 'children': [],
- },
- {
- 'componentName': 'TinyTabItem',
- 'id': 'p0q1r2s3',
- 'props': {
- 'title': '企业办公',
- 'name': '企业办公',
- },
- 'children': [],
- },
- ],
- },
- {
- 'componentName': 'CanvasFlexBox',
- 'id': 't4u5v6w7',
- 'props': {
- 'justifyContent': 'center',
- 'marginTop': '20px',
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'id': 'x8y9z0a1',
- 'props': {
- 'text': '查看企业应用中心 >',
- 'style': 'font-size: 16px;',
- },
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'CanvasFlexBox',
- 'id': 'b7a4c9f2',
- 'props': {
- 'flexDirection': 'column',
- 'justifyContent': 'center',
- 'alignItems': 'center',
- },
- 'children': [
- {
- 'componentName': 'TinyCarousel',
- 'id': 'e8d3a5b1',
- 'props': {
- 'height': '600px',
- 'autoplay': true,
- 'interval': 5000,
- },
- 'children': [
- {
- 'componentName': 'TinyCarouselItem',
- 'props': {
- 'title': 'carousel-item-b',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'margin:10px 0 0 30px',
- },
- 'id': '55c45252',
- },
- ],
- 'id': '32322a23',
- },
- ],
- },
- {
- 'componentName': 'CanvasFlexBox',
- 'id': 'x8y9z0a1',
- 'props': {
- 'flexDirection': 'row',
- 'justifyContent': 'space-around',
- 'alignItems': 'center',
- 'style': 'width: 100%; height: 80px; background-color: #f5f5f5;',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'id': 'b2c3d4e5',
- 'props': {
- 'style': 'display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'id': 'f6g7h8i9',
- 'props': {
- 'text': '华为云618',
- 'style': 'font-size: 18px; font-weight: bold;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'j0k1l2m3',
- 'props': {
- 'text': '智惠行·云无忧',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'n4o5p6q7',
- 'props': {
- 'style': 'display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'id': 'r8s9t0u1',
- 'props': {
- 'text': '免费体验中心',
- 'style': 'font-size: 18px; font-weight: bold;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'v2w3x4y5',
- 'props': {
- 'text': '提供80+精选云产品,立即免费试用',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'z6a7b8c9',
- 'props': {
- 'style': 'display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'id': 'd0e1f2g3',
- 'props': {
- 'text': 'MaaS上线MCP',
- 'style': 'font-size: 18px; font-weight: bold;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 'h4i5j6k7',
- 'props': {
- 'text': '解锁专属AI Agent,高效构建智能化应用场景',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- {
- 'componentName': 'div',
- 'id': 'l8m9n0o1',
- 'props': {
- 'style': 'display: flex; flex-direction: column; justify-content: center; align-items: center;',
- },
- 'children': [
- {
- 'componentName': 'Text',
- 'id': 'p2q3r4s5',
- 'props': {
- 'text': '黄大年茶思屋',
- 'style': 'font-size: 18px; font-weight: bold;',
- },
- },
- {
- 'componentName': 'Text',
- 'id': 't6u7v8w9',
- 'props': {
- 'text': '开放的科学与技术交流平台',
- 'style': 'font-size: 14px; color: #666;',
- },
- },
- ],
- },
- ],
- },
- ],
- },
- {
- 'componentName': 'TinyCarousel',
- 'props': {
- 'height': '180px',
- 'className': 'component-base-style',
- },
- 'children': [
- {
- 'componentName': 'TinyCarouselItem',
- 'props': {
- 'title': 'carousel-item-a',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'margin:10px 0 0 30px',
- },
- 'id': '412223b3',
- 'children': [
- {
- 'componentName': 'Img',
- 'props': {
- 'src': 'https://tinyengine-assets.obs.cn-north-4.myhuaweicloud.com/files/designer-default-icon.jpg',
- 'className': 'component-base-style',
- },
- 'children': [],
- 'id': '23563383',
- },
- ],
- },
- ],
- 'id': '65255135',
- },
- {
- 'componentName': 'TinyCarouselItem',
- 'props': {
- 'title': 'carousel-item-b',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'margin:10px 0 0 30px',
- },
- 'id': '64234622',
- },
- ],
- 'id': 'd62c4365',
- },
- ],
- 'id': '4243de46',
- },
- {
- 'componentName': 'TinyTabs',
- 'props': {
- 'modelValue': 'first',
- 'className': 'component-base-style',
- },
- 'children': [
- {
- 'componentName': 'TinyTabItem',
- 'props': {
- 'title': '标签页1',
- 'name': 'first',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'margin:10px 0 0 30px',
- },
- 'id': '3553655f',
- },
- ],
- 'id': '53155552',
- },
- {
- 'componentName': 'TinyTabItem',
- 'props': {
- 'title': '标签页2',
- 'name': 'second',
- },
- 'children': [
- {
- 'componentName': 'div',
- 'props': {
- 'style': 'margin:10px 0 0 30px',
- },
- 'id': '23b42cf6',
- },
- ],
- 'id': '25244454',
- },
- ],
- 'id': '24532395',
- },
- ],
- 'dataSource': {
- 'list': [],
- },
- 'methods': {},
- 'bridge': {
- 'imports': [],
- },
- 'state': {},
- 'inputs': [],
- 'outputs': [],
- 'id': 'body',
-};
-
-export const examples = [
- { name: '双向绑定的表单', schema: formSchema },
- { name: '信息展示卡片', schema: infoCardSchema },
- { name: '表格卡片', schema: gridSchema },
- { name: 'Tabs卡片', schema: tabsSchema },
-];
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/extend.json b/packages/materials/vue-opentiny-vue/src/render-config/extend.json
deleted file mode 100644
index 8c64492d..00000000
--- a/packages/materials/vue-opentiny-vue/src/render-config/extend.json
+++ /dev/null
@@ -1,833 +0,0 @@
-{
- "data": {
- "framework": "Vue",
- "materials": {
- "components": [
- {
- "name": {
- "zh_CN": "卡片组件"
- },
- "component": "TinyCard",
- "icon": "card",
- "description": "强大卡片组件,用于包裹展示内容。",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- },
- "group": "component",
- "configure": {
- },
- "schema": {
- "properties": [
- {
- "label": {
- "zh_CN": "基础属性"
- },
- "description": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "auto-width",
- "label": {
- "text": {
- "zh_CN": "自动撑开"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "卡片的宽度是否自动撑开,设置后将不再给卡片设置固定宽度"
- }
- },
- {
- "property": "type",
- "label": {
- "text": {
- "zh_CN": "卡片类型"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "设置卡片类型,可选值为\"text\", \"image\", \"video\", \"logo\", 默认是\"text\""
- }
- },
- {
- "property": "src",
- "label": {
- "text": {
- "zh_CN": "图片或者视频的地址"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "图片或者视频的地址"
- }
- },
- {
- "property": "title",
- "label": {
- "text": {
- "zh_CN": "卡片的标题,字号比正文略大,比h3小"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "卡片的标题,字号比正文略大,比h3小"
- }
- }
- ]
- }
- ]
- }
- },
- {
- "name": {
- "zh_CN": "可交互按钮"
- },
- "component": "ActionButton",
- "icon": "card",
- "description": "可交互按钮,已默认绑定了点击事件,使用时禁止再绑定点击事件,若要绑定事件,请使用TinyButton组件",
- "doc_url": "",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- },
- "group": "component",
- "configure": {
- },
- "schema": {
- "properties": [
- {
- "label": {
- "zh_CN": "基础属性"
- },
- "description": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "text",
- "type": "string",
- "defaultValue": "按钮文案",
- "label": {
- "text": {
- "zh_CN": "按钮文字"
- }
- },
- "cols": 12,
- "hidden": false,
- "required": true,
- "readOnly": false,
- "disabled": false,
- "widget": {
- "component": "I18nConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": "按钮文字"
- },
- "labelPosition": "left"
- },
- {
- "property": "size",
- "type": "select",
- "label": {
- "text": {
- "zh_CN": "大小"
- }
- },
- "cols": 12,
- "rules": [
- ],
- "hidden": false,
- "required": true,
- "readOnly": false,
- "disabled": false,
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "large",
- "value": "large"
- },
- {
- "label": "medium",
- "value": "medium"
- },
- {
- "label": "small",
- "value": "small"
- },
- {
- "label": "mini",
- "value": "mini"
- }
- ]
- }
- },
- "description": {
- "zh_CN": "按钮大小"
- },
- "labelPosition": "left"
- },
- {
- "property": "disabled",
- "label": {
- "text": {
- "zh_CN": "禁用"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "CheckBoxConfigurator",
- "props": {
- }
- },
- "description": {
- "zh_CN": "是否被禁用"
- },
- "labelPosition": "left"
- },
- {
- "property": "type",
- "label": {
- "text": {
- "zh_CN": "类型"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "primary",
- "value": "primary"
- },
- {
- "label": "success",
- "value": "success"
- },
- {
- "label": "info",
- "value": "info"
- },
- {
- "label": "warning",
- "value": "warning"
- },
- {
- "label": "danger",
- "value": "danger"
- },
- {
- "label": "text",
- "value": "text"
- }
- ]
- }
- },
- "description": {
- "zh_CN": "设置不同的主题样式"
- },
- "labelPosition": "left"
- }
- ]
- }
- ]
- }
- },
- {
- "name": {
- "zh_CN": "ol"
- },
- "component": "有序列表",
- "description": "有序列表",
- "group": "component"
- },
- {
- "name": {
- "zh_CN": "ul"
- },
- "component": "无序列表",
- "description": "无序列表",
- "group": "component"
- },
- {
- "name": {
- "zh_CN": "li"
- },
- "component": "列表项",
- "description": "列表项",
- "group": "component"
- },
- {
- "name": {
- "zh_CN": "看板画布"
- },
- "component": "GridStack",
- "description": "看板画布,可完成对看板瓷砖的布局",
- "group": "component",
- "schema": {
- "properties": [
- ],
- "slots": {
- "default": {
- "label": {
- "zh_CN": "自定义看板内容"
- },
- "description": {
- "zh_CN": "看板画布的内容,通常为看板瓷砖列表"
- }
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "看板瓷砖组件"
- },
- "description": "看板瓷砖,包裹展示内容,生成看板所需参数,看板在画布中完成布局,画布整体由12 * 12个格子排列,举例:看板占据2行2列,参数各项取值为[{x: 0, y: 0, w: 2, h: 2}]",
- "component": "GridStackItem",
- "group": "component",
- "schema": {
- "properties": [
- {
- "label": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "x",
- "label": {
- "text": {
- "zh_CN": "整体布局中横坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
- }
- },
- "description": {
- "zh_CN": "整体布局中横坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "type": "number"
- },
- {
- "property": "y",
- "label": {
- "text": {
- "zh_CN": "整体布局中纵坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
- }
- },
- "description": {
- "zh_CN": "整体布局中纵坐标,每个图片按高度和宽度占用情况分配坐标,取值从0开始"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "type": "number"
- },
- {
- "property": "w",
- "label": {
- "text": {
- "zh_CN": "看板在画布中占据的列数,画布总共12列,即该数值取值范围为0到11"
- }
- },
- "description": {
- "zh_CN": "看板在画布中占据的列数,画布总共12列,即该数值取值范围为0到11"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "type": "number"
- },
- {
- "property": "h",
- "label": {
- "text": {
- "zh_CN": "看板在画布中占据的行数,画布总共12行,即该数值取值范围为0到11"
- }
- },
- "description": {
- "zh_CN": "看板在画布中占据的行数,画布总共12行,即该数值取值范围为0到11"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "type": "number"
- },
- {
- "property": "id",
- "label": {
- "text": {
- "zh_CN": "唯一标识"
- }
- },
- "description": {
- "zh_CN": "唯一标识,要保证唯一性"
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "type": "string"
- },
- {
- "property": "autoPosition",
- "label": {
- "text": {
- "zh_CN": "是否开启自动在画布中定位"
- }
- },
- "description": {
- "zh_CN": "是否开启自动在画布中定位"
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "type": "string"
- }
- ]
- }
- ],
- "slots": {
- "default": {
- "label": {
- "zh_CN": "自定义看板瓷砖内容"
- },
- "description": {
- "zh_CN": "可以使用其他组件作为瓷砖内容,也可以自定义实现"
- }
- }
- }
- }
- },
- {
- "name": {
- "zh_CN": "单选按钮组"
- },
- "component": "TinyRadioGroup",
- "icon": "radio-group",
- "description": "用于在一组选项中进行单选。",
- "doc_url": "https://www.opentiny.design/tiny-vue/components/radio",
- "screenshot": "",
- "tags": "",
- "keywords": "",
- "dev_mode": "proCode",
- "npm": {
- },
- "group": "component",
- "configure": {
- },
- "schema": {
- "properties": [
- {
- "label": {
- "zh_CN": "基础属性"
- },
- "description": {
- "zh_CN": "基础属性"
- },
- "content": [
- {
- "property": "modelValue",
- "label": {
- "text": {
- "zh_CN": "绑定值"
- }
- },
- "required": true,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "单选框组的绑定值"
- }
- },
- {
- "property": "options",
- "label": {
- "text": {
- "zh_CN": "选项列表"
- }
- },
- "defaultValue": [],
- "required": true,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "单选按钮选项列表,配置单选组的值、文本和点击事件。示例:[{label: '1', text: '选项1', events: {click: () => {console.log('点击选项1')}}}]"
- }
- },
- {
- "property": "disabled",
- "label": {
- "text": {
- "zh_CN": "禁用"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "是否禁用整个单选组"
- }
- },
- {
- "property": "type",
- "label": {
- "text": {
- "zh_CN": "展示形式"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "widget": {
- "component": "ButtonGroupConfigurator",
- "props": {
- "options": [
- {
- "label": "radio",
- "value": "radio"
- },
- {
- "label": "button",
- "value": "button"
- }
- ]
- }
- },
- "description": {
- "zh_CN": "单选组的展示形式,可选值为:radio(单选框) 、 button(按钮、选项式)"
- }
- },
- {
- "property": "size",
- "label": {
- "text": {
- "zh_CN": "尺寸"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "cols": 12,
- "widget": {
- "component": "SelectConfigurator",
- "props": {
- "options": [
- {
- "label": "medium",
- "value": "medium"
- },
- {
- "label": "small",
- "value": "small"
- },
- {
- "label": "mini",
- "value": "mini"
- }
- ]
- }
- },
- "description": {
- "zh_CN": "单选组尺寸, 可选值有 medium 、 small 、 mini"
- }
- },
- {
- "property": "vertical",
- "label": {
- "text": {
- "zh_CN": "垂直排列"
- }
- },
- "required": false,
- "readOnly": false,
- "disabled": false,
- "description": {
- "zh_CN": "是否垂直展示单选按钮"
- }
- }
- ]
- }
- ],
- "events": {
- "onChange": {
- "label": {
- "zh_CN": "选中值变化时触发"
- },
- "description": {
- "zh_CN": "选中值变化时触发"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "value",
- "type": "string",
- "defaultValue": "",
- "description": {
- "zh_CN": "当前选中的值"
- }
- }
- ],
- "returns": {
- }
- },
- "defaultValue": ""
- },
- "onUpdate:modelValue": {
- "label": {
- "zh_CN": "绑定值更新时触发"
- },
- "description": {
- "zh_CN": "v-model 对应的值更新时触发"
- },
- "type": "event",
- "functionInfo": {
- "params": [
- {
- "name": "value",
- "type": "string",
- "defaultValue": "",
- "description": {
- "zh_CN": "更新后的绑定值"
- }
- }
- ],
- "returns": {
- }
- },
- "defaultValue": ""
- }
- }
- }
- }
- ],
- "snippets": [
- {
- "group": "Card",
- "label": {
- "zh_CN": "卡片"
- },
- "children": [
- {
- "name": {
- "zh_CN": "内容展示卡片"
- },
- "snippetName": "TinyCard",
- "schema": {
- "componentName": "TinyCard",
- "children": [
- {
- "componentName": "h2",
- "children": "员工信息列表"
- },
- {
- "componentName": "TinyGrid",
- "props": {
- "editConfig": {
- "trigger": "click",
- "mode": "cell",
- "showStatus": true
- },
- "columns": [
- {
- "type": "index",
- "width": 60
- },
- {
- "type": "selection",
- "width": 60
- },
- {
- "field": "employees",
- "title": "员工数"
- },
- {
- "field": "created_date",
- "title": "创建日期"
- },
- {
- "field": "city",
- "title": "城市"
- }
- ],
- "data": [
- {
- "id": "1",
- "name": "GFD科技有限公司",
- "city": "福州",
- "employees": 800,
- "created_date": "2014-04-30 00:56:00",
- "boole": false
- },
- {
- "id": "2",
- "name": "WWW科技有限公司",
- "city": "深圳",
- "employees": 300,
- "created_date": "2016-07-08 12:36:22",
- "boole": true
- }
- ]
- }
- }
- ]
- }
- },
- {
- "name": {
- "zh_CN": "图片卡片"
- },
- "snippetName": "TinyCard",
- "schema": {
- "componentName": "TinyCard",
- "props": {
- "title": "卡片标题",
- "type": "image",
- "src": "https://res.hc-cdn.com/tiny-vue-web-doc/3.26.1/static/images/dsj.png"
- },
- "children": [
- {
- "componentName": "p",
- "children": "这是一段长文本内容,这是一段长文本内容,这是一段长文本内容,这是一段长文本内容。"
- }
- ]
- }
- }
- ]
- },
- {
- "group": "list",
- "label": {
- "zh_CN": "列表"
- },
- "children": [
- {
- "name": {
- "zh_CN": "无序列表"
- },
- "snippetName": "ul",
- "schema": {
- "componentName": "ul",
- "children": [
- {
- "componentName": "li",
- "children": "无序列表项1"
- },
- {
- "componentName": "li",
- "children": "无序列表项2"
- }
- ]
- }
- },
- {
- "name": {
- "zh_CN": "有序列表"
- },
- "snippetName": "ol",
- "schema": {
- "componentName": "ol",
- "children": [
- {
- "componentName": "li",
- "children": "有序列表项1"
- },
- {
- "componentName": "li",
- "children": "有序列表项2"
- }
- ]
- }
- }
- ]
- },
- {
- "group": "RadioGroup",
- "label": {
- "zh_CN": "单选按钮组"
- },
- "children": [
- {
- "name": {
- "zh_CN": "基础单选组"
- },
- "snippetName": "TinyRadioGroup",
- "schema": {
- "componentName": "TinyRadioGroup",
- "props": {
- "modelValue": "1",
- "options": [
- {
- "label": "1",
- "text": "选项1"
- },
- {
- "label": "2",
- "text": "选项2"
- },
- {
- "label": "3",
- "text": "选项3"
- }
- ]
- }
- }
- },
- {
- "name": {
- "zh_CN": "选项式单选组"
- },
- "snippetName": "TinyRadioGroup",
- "schema": {
- "componentName": "TinyRadioGroup",
- "props": {
- "modelValue": "2",
- "type": "button",
- "options": [
- {
- "label": "1",
- "text": "选项1"
- },
- {
- "label": "2",
- "text": "选项2"
- },
- {
- "label": "3",
- "text": "选项3"
- }
- ]
- }
- }
- }
- ]
- }
- ]
- }
- }
-}
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/index.ts b/packages/materials/vue-opentiny-vue/src/render-config/index.ts
deleted file mode 100644
index 38f29768..00000000
--- a/packages/materials/vue-opentiny-vue/src/render-config/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './merge';
diff --git a/packages/materials/vue-opentiny-vue/src/render-config/merge.ts b/packages/materials/vue-opentiny-vue/src/render-config/merge.ts
deleted file mode 100644
index ef2d9b24..00000000
--- a/packages/materials/vue-opentiny-vue/src/render-config/merge.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import bundleJson from './bundle.json' with { type: 'json' };
-import builtinJson from './builtin.json' with { type: 'json' };
-import chartJson from './chart.json' with { type: 'json' };
-import extendJson from './extend.json' with { type: 'json' };
-import { examples } from './example-schema';
-import { whiteList } from './white-list';
-
-// 定义渲染器配置的类型
-export interface IRendererConfig {
- materialsList: any[];
- examples: any[];
- whiteList: string[];
-}
-
-export const rendererConfig: IRendererConfig = {
- materialsList: [bundleJson, builtinJson, chartJson, extendJson],
- examples,
- whiteList,
-};
diff --git a/packages/materials/vue-opentiny-vue/vite.config.ts b/packages/materials/vue-opentiny-vue/vite.config.ts
index d109b201..0c73f148 100644
--- a/packages/materials/vue-opentiny-vue/vite.config.ts
+++ b/packages/materials/vue-opentiny-vue/vite.config.ts
@@ -18,14 +18,17 @@ export default defineConfig({
lib: {
entry: {
index: path.resolve(__dirname, './src/index.ts'),
- 'render-config': path.resolve(__dirname, './src/render-config/index.ts'),
- 'extend-renderer': path.resolve(__dirname, './src/extend-renderer.ts'),
+ meta: path.resolve(__dirname, './src/meta/index.ts'),
+ materials: path.resolve(__dirname, './src/materials/index.ts'),
},
formats: ['es'],
fileName: (format, entryName) => `${entryName}.js`,
},
+ sourcemap: true,
rollupOptions: {
- external: [...Object.keys(packageJson.dependencies || {}).map(name => new RegExp(`^${escapeStringRegexp(name)}(/|$)`))],
+ external: [
+ ...Object.keys(packageJson.dependencies || {}).map((name) => new RegExp(`^${escapeStringRegexp(name)}(/|$)`)),
+ ],
},
},
});
diff --git a/packages/server/README.md b/packages/server/README.md
index c648242f..bf7e65b0 100644
--- a/packages/server/README.md
+++ b/packages/server/README.md
@@ -7,7 +7,6 @@ A server for the OpenTiny GenUI SDK to enhance LLM return structure stream conte
* **OpenAI Compatible:** Drop-in replacement for OpenAI chat completions API.
* **Easy Integration:** Programmatic API or CLI to start the server.
-
## Usage
### CLI
@@ -50,7 +49,6 @@ equipChatCompletions(app, {
app.listen(3100);
```
-
## Documentation
* [Server Usage Guide](https://docs.opentiny.design/genui-sdk/guide/server-usage)
@@ -58,6 +56,3 @@ app.listen(3100);
## API
* [Server API](https://docs.opentiny.design/genui-sdk/components/server/api)
-
-
-
diff --git a/packages/server/package.json b/packages/server/package.json
index 6287d849..d48d0383 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -26,8 +26,8 @@
},
"exports": {
".": {
- "import": "./output/dist/index.js",
- "types": "./output/dist/index.d.ts"
+ "types": "./output/dist/index.d.ts",
+ "import": "./output/dist/index.js"
}
},
"files": [
@@ -44,6 +44,7 @@
"dev": "tsx watch --tsconfig ./tsconfig.dev.json test/start.ts"
},
"dependencies": {
+ "@opentiny/genui-sdk-core": "workspace:*",
"cors": "^2.8.5",
"dotenv": "^16.6.1",
"commander": "^14.0.0",
@@ -53,7 +54,6 @@
},
"devDependencies": {
"@opentiny/genui-sdk-chat-completions": "workspace:*",
- "@opentiny/genui-sdk-core": "workspace:*",
"@types/express": "^5.0.3",
"@types/node": "^20.0.0",
"@types/commander": "^2.12.2",
diff --git a/packages/server/tsconfig.dev.json b/packages/server/tsconfig.dev.json
index bfe9124e..adccf900 100644
--- a/packages/server/tsconfig.dev.json
+++ b/packages/server/tsconfig.dev.json
@@ -8,11 +8,11 @@
"@opentiny/genui-sdk-core": [
"../core/src/index.ts"
],
- "@opentiny/genui-sdk-materials-vue-opentiny-vue/render-config": [
- "../materials/vue-opentiny-vue/src/render-config/index.ts"
+ "@opentiny/genui-sdk-materials-vue-opentiny-vue/meta": [
+ "../materials/vue-opentiny-vue/src/meta/index.ts"
],
- "@opentiny/genui-sdk-materials-angular-opentiny-ng/render-config": [
- "../materials/angular-opentiny-ng/src/render-config/index.ts"
+ "@opentiny/genui-sdk-materials-angular-opentiny-ng/meta": [
+ "../materials/angular-opentiny-ng/src/meta/index.ts"
]
}
},
diff --git a/packages/server/vite.config.ts b/packages/server/vite.config.ts
index 1a2b2ed2..5b9e35ac 100644
--- a/packages/server/vite.config.ts
+++ b/packages/server/vite.config.ts
@@ -10,7 +10,7 @@ export default defineConfig(({ mode }) => {
const plugins = [
dts({
rollupTypes: true,
- bundledPackages: ['@opentiny/genui-sdk-core', '@opentiny/genui-sdk-chat-completions'],
+ bundledPackages: ['@opentiny/genui-sdk-chat-completions'],
}),
jsconfigPaths({
projects: ['./tsconfig.json'],
@@ -37,12 +37,9 @@ export default defineConfig(({ mode }) => {
formats: ['es'],
},
outDir: 'output/dist',
- sourcemap: mode === 'no-obfuscator',
+ sourcemap: true,
rollupOptions: {
external: (id) => {
- if (id.includes('@opentiny/genui-sdk-core')) {
- return false;
- }
if (id.startsWith('node:')) {
return true;
}
diff --git a/patches/@opentiny__ng-checkbox.patch b/patches/@opentiny__ng-checkbox.patch
deleted file mode 100644
index d437fdf5..00000000
--- a/patches/@opentiny__ng-checkbox.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff --git a/fesm2020/opentiny-ng-checkbox.mjs b/fesm2020/opentiny-ng-checkbox.mjs
-index 6b33941eea01dd43c553ea92ea8dcf179ebebc41..306a70a0f49bca6e723be8a1a79dfa5f03383dca 100644
---- a/fesm2020/opentiny-ng-checkbox.mjs
-+++ b/fesm2020/opentiny-ng-checkbox.mjs
-@@ -734,14 +734,14 @@ class TiCheckboxGroupComponent extends TiFormComponent {
- }
- }
- TiCheckboxGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: TiCheckboxGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
--TiCheckboxGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: TiCheckboxGroupComponent, selector: "ti-checkbox-group", inputs: { items: "items", labelKey: "labelKey", valueKey: "valueKey", direction: "direction" }, host: { properties: { "class.ti-checkboxgroup-horizon": "direction === \"horizontal\"", "class.ti-checkboxgroup-vertical": "direction === \"vertical\"", "class.ti-checkboxgroup-defalut-item": "!itemTemplate" } }, providers: [TiFormComponent.getValueAccessor(TiCheckboxGroupComponent)], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", styles: ["ti-checkbox-group{display:inline-flex;flex-wrap:wrap;line-height:1.5em;vertical-align:bottom}ti-checkbox-group .ti3-checkbox{display:inline-flex!important;align-items:flex-start!important;flex-shrink:0;line-height:1.5em!important}ti-checkbox-group.ti-checkboxgroup-vertical{flex-direction:column}ti-checkbox-group.ti-checkboxgroup-vertical input[type=checkbox][tiCheckbox]+.ti3-checkbox,ti-checkbox-group.ti-checkboxgroup-vertical .checkbox-group-item{line-height:28px!important;line-height:var(--ti-common-size-7x, 28px)!important;flex-shrink:0}.checkbox-group-item{display:inline-flex}ti-checkbox-group.ti-checkboxgroup-horizon.ti-checkboxgroup-defalut-item label.ti3-checkbox{margin-right:20px;margin-right:var(--ti-common-space-5x, 20px)}\n"], components: [{ type: TiCheckgroupComponent, selector: "[tiCheckgroup]", inputs: ["items", "checkeds"], outputs: ["checkedsChange"] }, { type: TiCheckitemComponent, selector: "[tiCheckitem]", inputs: ["item", "beCheckeds", "valueKey"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
-+TiCheckboxGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: TiCheckboxGroupComponent, selector: "ti-checkbox-group", inputs: { items: "items", labelKey: "labelKey", valueKey: "valueKey", direction: "direction" }, host: { properties: { "class.ti-checkboxgroup-horizon": "direction === \"horizontal\"", "class.ti-checkboxgroup-vertical": "direction === \"vertical\"", "class.ti-checkboxgroup-defalut-item": "!itemTemplate" } }, providers: [TiFormComponent.getValueAccessor(TiCheckboxGroupComponent)], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", styles: ["ti-checkbox-group{display:inline-flex;flex-wrap:wrap;line-height:1.5em;vertical-align:bottom}ti-checkbox-group .ti3-checkbox{display:inline-flex!important;align-items:flex-start!important;flex-shrink:0;line-height:1.5em!important}ti-checkbox-group.ti-checkboxgroup-vertical{flex-direction:column}ti-checkbox-group.ti-checkboxgroup-vertical input[type=checkbox][tiCheckbox]+.ti3-checkbox,ti-checkbox-group.ti-checkboxgroup-vertical .checkbox-group-item{line-height:28px!important;line-height:var(--ti-common-size-7x, 28px)!important;flex-shrink:0}.checkbox-group-item{display:inline-flex}ti-checkbox-group.ti-checkboxgroup-horizon.ti-checkboxgroup-defalut-item label.ti3-checkbox{margin-right:20px;margin-right:var(--ti-common-space-5x, 20px)}\n"], components: [{ type: TiCheckgroupComponent, selector: "[tiCheckgroup]", inputs: ["items", "checkeds"], outputs: ["checkedsChange"] }, { type: TiCheckitemComponent, selector: "[tiCheckitem]", inputs: ["item", "beCheckeds", "valueKey"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: TiCheckboxGroupComponent, decorators: [{
- type: Component,
- args: [{ selector: 'ti-checkbox-group', encapsulation: ViewEncapsulation.None, host: {
- '[class.ti-checkboxgroup-horizon]': 'direction === "horizontal"',
- '[class.ti-checkboxgroup-vertical]': 'direction === "vertical"',
- '[class.ti-checkboxgroup-defalut-item]': '!itemTemplate'
-- }, changeDetection: ChangeDetectionStrategy.OnPush, providers: [TiFormComponent.getValueAccessor(TiCheckboxGroupComponent)], template: "\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", styles: ["ti-checkbox-group{display:inline-flex;flex-wrap:wrap;line-height:1.5em;vertical-align:bottom}ti-checkbox-group .ti3-checkbox{display:inline-flex!important;align-items:flex-start!important;flex-shrink:0;line-height:1.5em!important}ti-checkbox-group.ti-checkboxgroup-vertical{flex-direction:column}ti-checkbox-group.ti-checkboxgroup-vertical input[type=checkbox][tiCheckbox]+.ti3-checkbox,ti-checkbox-group.ti-checkboxgroup-vertical .checkbox-group-item{line-height:28px!important;line-height:var(--ti-common-size-7x, 28px)!important;flex-shrink:0}.checkbox-group-item{display:inline-flex}ti-checkbox-group.ti-checkboxgroup-horizon.ti-checkboxgroup-defalut-item label.ti3-checkbox{margin-right:20px;margin-right:var(--ti-common-space-5x, 20px)}\n"] }]
-+ }, changeDetection: ChangeDetectionStrategy.OnPush, providers: [TiFormComponent.getValueAccessor(TiCheckboxGroupComponent)], template: "\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n", styles: ["ti-checkbox-group{display:inline-flex;flex-wrap:wrap;line-height:1.5em;vertical-align:bottom}ti-checkbox-group .ti3-checkbox{display:inline-flex!important;align-items:flex-start!important;flex-shrink:0;line-height:1.5em!important}ti-checkbox-group.ti-checkboxgroup-vertical{flex-direction:column}ti-checkbox-group.ti-checkboxgroup-vertical input[type=checkbox][tiCheckbox]+.ti3-checkbox,ti-checkbox-group.ti-checkboxgroup-vertical .checkbox-group-item{line-height:28px!important;line-height:var(--ti-common-size-7x, 28px)!important;flex-shrink:0}.checkbox-group-item{display:inline-flex}ti-checkbox-group.ti-checkboxgroup-horizon.ti-checkboxgroup-defalut-item label.ti3-checkbox{margin-right:20px;margin-right:var(--ti-common-space-5x, 20px)}\n"] }]
- }], propDecorators: { items: [{
- type: Input
- }], labelKey: [{
diff --git a/patches/@opentiny__vue-form-item@3.28.0.patch b/patches/@opentiny__vue-form-item@3.28.0.patch
new file mode 100644
index 00000000..ab036f9a
--- /dev/null
+++ b/patches/@opentiny__vue-form-item@3.28.0.patch
@@ -0,0 +1,22 @@
+diff --git a/lib/pc.js b/lib/pc.js
+index 332f542b78b90a6dcb4eb6569169457ec0826592..1e457bd67e838b5e393d479bcda447dcd8980125 100644
+--- a/lib/pc.js
++++ b/lib/pc.js
+@@ -95,7 +95,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
+ });
+ },
+ render: function render() {
+- var _state$formInstance, _state$formInstance2, _state$formInstance3, _state$formInstance4, _this = this, _class, _class2, _class3, _class4, _class5;
++ var _state$formInstance, _state$formInstance2, _state$formInstance3, _state$formInstance4, _state$formInstance5, _this = this, _class, _class2, _class3, _class4, _class5;
+ var state = this.state, required = this.required, slots = this.slots, label = this.label, scopedSlots = this.scopedSlots, showMessage = this.showMessage, inlineMessage = this.inlineMessage, ellipsis = this.ellipsis, vertical = this.vertical, handleLabelMouseenter = this.handleLabelMouseenter, handleMouseleave = this.handleMouseleave;
+ var validateIcon = state.validateIcon, isErrorInline = state.isErrorInline, isErrorBlock = state.isErrorBlock, tooltipType = state.tooltipType;
+ var isMobile = state.mode === "mobile";
+@@ -111,7 +111,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
+ var formAppendToBody = (_state$formInstance3 = state.formInstance) == null ? void 0 : _state$formInstance3.appendToBody;
+ var appendToBody = typeof this.appendToBody === "boolean" ? this.appendToBody : typeof formAppendToBody === "boolean" ? formAppendToBody : true;
+ var validatePosition = this.validatePosition || ((_state$formInstance4 = state.formInstance) == null ? void 0 : _state$formInstance4.validatePosition) || "top-end";
+- var popperOptions = _extends({}, state.formInstance.popperOptions, this.popperOptions, {
++ var popperOptions = _extends({}, (_state$formInstance5 = state.formInstance) == null ? void 0 : _state$formInstance5.popperOptions, this.popperOptions, {
+ forceAbsolute: !appendToBody,
+ onUpdate: function onUpdate(options) {
+ var popper = options.instance._popper;
diff --git a/patches/@opentiny__vue-grid@3.28.0.patch b/patches/@opentiny__vue-grid@3.28.0.patch
new file mode 100644
index 00000000..5dfafba2
--- /dev/null
+++ b/patches/@opentiny__vue-grid@3.28.0.patch
@@ -0,0 +1,42 @@
+diff --git a/lib/index.js b/lib/index.js
+index fc662a8ce85dbd67b4832961431e8082306ca991..680baed0d9d31ff31eb9401519975a9d8cb68dca 100644
+--- a/lib/index.js
++++ b/lib/index.js
+@@ -5,7 +5,7 @@ import { debounce, PopupManager, PopperJS, extend, browserInfo, isObject, isEmpt
+ import { iconError, iconSortTriangleDescending, iconSortTriangleAscending, iconSortTriangle, iconUnfilter, iconEdit, iconConmentRefresh, iconMinscreen, iconFullscreen, iconSetting, iconChevronRight, iconChevronDown, iconGridNoData, iconRadio, iconRadioselected, iconSearch, iconCheckedSur, iconCheck, iconHalfselect, iconArrowBottom, IconEllipsis, iconClose, iconYes, iconExpand, iconPutAway, iconEllipsis, iconMarkOn } from '@opentiny/vue-icon';
+ import { $prefix, hooks, defineComponent, h, $install, isVue2, isVnode, $props, mergeClass, resolveTheme, useInstanceSlots, useRelation, emitter, resolveMode, useBreakpoint, setup as setup$1 } from '@opentiny/vue-common';
+ import { uniqueId, toNumber as toNumber$1, isBoolean, each, isObject as isObject$1, isFunction, isArray, findIndexOf, get, set, clone, clear, destructuring, mapTree, eachTree, has, isUndefined, isEqual, find as find$1, filterTree, arrayEach, isNumber, findTree as findTree$1, sum, template, assign, objectMap, sortBy, isString, remove, toStringJSON, toArray, arrayIndexOf } from '@opentiny/vue-renderless/grid/static/';
+-import { getFuncText, getDomNode, getRowid, getEventTargetNode, isScale, emitEvent, hasChildrenList, getListeners, getOffsetPos, getFilters, getColumnConfig, formatText, getRowkey, getRowUniqueId, setCellValue, getColumnList, repairFixed, rowToVisible, colToVisible, getCell, assemColumn, GlobalEvent, getCellValue, updateCellTitle, isPx, getClass, getRowNodes, getCellNodeIndex } from '@opentiny/vue-renderless/grid/utils';
++import { getFuncText, getDomNode, getRowid, getEventTargetNode, isScale, emitEvent, hasChildrenList, getListeners, resolveTableListeners, getOffsetPos, getFilters, getColumnConfig, formatText, getRowkey, getRowUniqueId, setCellValue, getColumnList, repairFixed, rowToVisible, colToVisible, getCell, assemColumn, GlobalEvent, getCellValue, updateCellTitle, isPx, getClass, getRowNodes, getCellNodeIndex } from '@opentiny/vue-renderless/grid/utils';
+ import Tooltip$1 from '@opentiny/vue-tooltip';
+ import { createVNode, mergeProps, isVNode, createTextVNode, resolveComponent, openBlock, createElementBlock, normalizeClass, createBlock, createCommentVNode, normalizeStyle, Fragment, renderList } from 'vue';
+ import { toNumber, findTree, find, isEqual as isEqual$1, arrayEach as arrayEach$1 } from '@opentiny/vue-renderless/grid/static';
+@@ -11485,6 +11485,7 @@ var Table = defineComponent({
+ },
+ render: function render14() {
+ var _class4;
++ this.tableListeners = resolveTableListeners(this);
+ var $grid = this.$grid, bodyProps = this.bodyProps, border = this.border, borderSaas = this.borderSaas, borderVertical = this.borderVertical;
+ var ctxMenuStore = this.ctxMenuStore, dropConfig = this.dropConfig, editConfig = this.editConfig, editRules = this.editRules, filterStore = this.filterStore;
+ var hasFilter2 = this.hasFilter, hasTip2 = this.hasTip, height2 = this.height, highlightCell = this.highlightCell, highlightHoverColumn = this.highlightHoverColumn, highlightHoverRow = this.highlightHoverRow;
+@@ -12058,8 +12059,8 @@ var Grid = defineComponent({
+ },
+ render: function render16() {
+ var _this50 = this;
+- var fetchOption = this.fetchOption, listeners = this.listeners, loading = this.loading, optimizOpt2 = this.optimizOpt, editConfigOpt2 = this.editConfigOpt, tooltipOpt2 = this.tooltipOpt, pager = this.pager, pagerConfig = this.pagerConfig, remoteFilter = this.remoteFilter, remoteSort = this.remoteSort, selectToolbar = this.selectToolbar;
+- var seqIndex2 = this.seqIndex, $slots = this.slots, tableCustoms2 = this.tableCustoms, tableData = this.tableData, tableListeners = this.tableListeners, tableLoading = this.tableLoading, tableProps2 = this.tableProps, toolbar = this.toolbar, vSize3 = this.vSize, designConfig = this.designConfig, viewType2 = this.viewType;
++ var fetchOption = this.fetchOption, eventsListeners = this.listeners, loading = this.loading, optimizOpt2 = this.optimizOpt, editConfigOpt2 = this.editConfigOpt, tooltipOpt2 = this.tooltipOpt, pager = this.pager, pagerConfig = this.pagerConfig, remoteFilter = this.remoteFilter, remoteSort = this.remoteSort, selectToolbar = this.selectToolbar;
++ var seqIndex2 = this.seqIndex, $slots = this.slots, tableCustoms2 = this.tableCustoms, tableData = this.tableData, tableLoading = this.tableLoading, tableProps2 = this.tableProps, toolbar = this.toolbar, vSize3 = this.vSize, designConfig = this.designConfig, viewType2 = this.viewType;
+ var columnAnchor = this.columnAnchor, columnAnchorParams = this.columnAnchorParams, fullScreenClass = this.fullScreenClass;
+ if (designConfig != null && designConfig.icons) {
+ Object.assign(GlobalConfig$1.icon, designConfig.icons);
+@@ -12073,7 +12074,8 @@ var Grid = defineComponent({
+ if ((designConfig == null ? void 0 : designConfig.stripe) !== void 0 && !props.stripe) {
+ props.stripe = designConfig == null ? void 0 : designConfig.stripe;
+ }
+- var tableOns = Object.assign(listeners, tableListeners);
++ var currentTableListeners = getListeners(this.$attrs, isVue2 ? this.$listeners : void 0);
++ var tableOns = Object.assign({}, eventsListeners, currentTableListeners);
+ var rowClassName = this.handleRowClassName, sortChangeEvent2 = this.sortChangeEvent, filterChangeEvent2 = this.filterChangeEvent;
+ if (fetchOption) {
+ Object.assign(props, {
diff --git a/patches/@opentiny__vue-renderless@3.28.2.patch b/patches/@opentiny__vue-renderless@3.28.2.patch
new file mode 100644
index 00000000..3d7188b9
--- /dev/null
+++ b/patches/@opentiny__vue-renderless@3.28.2.patch
@@ -0,0 +1,260 @@
+diff --git a/form/index.js b/form/index.js
+index e2a264d578f9512f8fd8a827f0669d71d7770411..b93fbbf32de9eb5cbd5ad3e71fb224d37215e099 100644
+--- a/form/index.js
++++ b/form/index.js
+@@ -53,8 +53,9 @@ const created = ({ parent, state }) => () => {
+ }
+ });
+ parent.$on("form:removeField", (field) => {
+- if (field.prop) {
+- state.fields.splice(state.fields.indexOf(field), 1);
++ const index = state.fields.indexOf(field);
++ if (index > -1) {
++ state.fields.splice(index, 1);
+ }
+ });
+ };
+diff --git a/form-item/index.js b/form-item/index.js
+index d458ae0bb1f22746e784e9ce92e29ea09aa81e60..562fd74ae3d4a32e901de2491a97d7f98a5dc470 100644
+--- a/form-item/index.js
++++ b/form-item/index.js
+@@ -160,27 +160,42 @@ const computedFieldValue = ({ props, state }) => () => {
+ }
+ return getPropByPath(model, path, true).v;
+ };
+-const mounted = ({ api, vm, props, state }) => () => {
++const registerField = ({ api, vm, props, state }) => () => {
++ if (!props.prop || state.fieldRegistered) {
++ return;
++ }
++ api.dispatch("Form", "form:addField", vm);
++ let initialValue = state.fieldValue;
++ if (Array.isArray(initialValue)) {
++ initialValue = [].concat(initialValue);
++ }
++ state.initialValue = initialValue;
++ api.addValidateEvents();
++ state.fieldRegistered = true;
++};
++const unregisterField = ({ api, vm, state }) => () => {
++ if (!state.fieldRegistered) {
++ return;
++ }
++ api.dispatch("Form", "form:removeField", vm);
++ api.removeValidateEvents();
++ state.fieldRegistered = false;
++};
++const updateTooltip = ({ vm, state }) => () => {
+ const tooltip = vm.$refs.tooltip;
+ if (tooltip) {
+ const content = vm.$refs.content;
+ tooltip.state.referenceElm = state.isMultiple ? content : content == null ? void 0 : content.children[0];
+ state.tooltip = tooltip;
+ }
+- if (props.prop) {
+- api.dispatch("Form", "form:addField", vm);
+- let initialValue = state.fieldValue;
+- if (Array.isArray(initialValue)) {
+- initialValue = [].concat(initialValue);
+- }
+- state.initialValue = initialValue;
+- api.addValidateEvents();
+- }
+ };
+-const unmounted = ({ api, vm, state }) => () => {
++const mounted = ({ api }) => () => {
++ api.updateTooltip();
++ api.registerField();
++};
++const unmounted = ({ api, state }) => () => {
+ state.canShowTip = false;
+- api.dispatch("Form", "form:removeField", vm);
+- api.removeValidateEvents();
++ api.unregisterField();
+ };
+ const validate = ({ api, props, state, t }) => (trigger, callback = () => void 0) => {
+ state.validateDisabled = false;
+@@ -203,6 +218,7 @@ const validate = ({ api, props, state, t }) => (trigger, callback = () => void 0
+ validator.validate(model, { firstFields: true }, (errors, invalidFields) => {
+ api.clearValidate();
+ const handlerError = () => {
++ api.updateTooltip();
+ state.validateState = !errors ? VALIDATE_STATE.Success : VALIDATE_STATE.Error;
+ if (errors && props.error) {
+ errors[0].message = props.error;
+@@ -295,7 +311,7 @@ const removeValidateEvents = (vm) => () => {
+ vm.$off("form.change");
+ vm.$off("displayed-value-changed");
+ };
+-const updateTip = ({ vm, state }) => () => {
++const updateTip = ({ api, vm, state }) => () => {
+ if (state.getValidateType !== "tip" && !state.canShowTip) {
+ return;
+ }
+@@ -401,6 +417,8 @@ export {
+ handleMouseenter,
+ handleMouseleave,
+ mounted,
++ registerField,
++ unregisterField,
+ onFieldBlur,
+ onFieldChange,
+ removeValidateEvents,
+@@ -408,6 +426,7 @@ export {
+ unmounted,
+ updateComputedLabelWidth,
+ updateTip,
++ updateTooltip,
+ validate,
+ watchError,
+ watchValidateStatus,
+diff --git a/form-item/vue.js b/form-item/vue.js
+index 40ba07091a6f1c2364ae724bc8859de7c0ad2b82..1010ef11e243c70715596dfdb6e4519fb2a3fab5 100644
+--- a/form-item/vue.js
++++ b/form-item/vue.js
+@@ -12,6 +12,8 @@ import {
+ removeValidateEvents,
+ mounted,
+ unmounted,
++ registerField,
++ unregisterField,
+ watchError,
+ watchValidateStatus,
+ computedLabelStyle,
+@@ -25,6 +27,7 @@ import {
+ computedIsErrorInline,
+ computedIsErrorBlock,
+ updateTip,
++ updateTooltip,
+ wrapValidate,
+ getDisplayedValue,
+ clearDisplayedValue,
+@@ -137,7 +140,8 @@ const initState = ({
+ return (_b = (_a = state.formInstance) == null ? void 0 : _a.state.tooltipType) != null ? _b : "normal";
+ }),
+ // 标记表单项下是否有多个子节点
+- isMultiple: false
++ isMultiple: false,
++ fieldRegistered: false
+ });
+ return state;
+ };
+@@ -147,7 +151,8 @@ const initApi = ({ api: api2, state, dispatch, broadcast, props, constants, vm,
+ dispatch,
+ broadcast,
+ watchError: watchError(state),
+- updateTip: updateTip({ vm, state }),
++ updateTip: updateTip({ api: api2, vm, state }),
++ updateTooltip: updateTooltip({ vm, state }),
+ watchValidateStatus: watchValidateStatus(state),
+ computedLabelStyle: computedLabelStyle({ props, state }),
+ computedValueStyle: computedValueStyle({ props, state }),
+@@ -162,8 +167,10 @@ const initApi = ({ api: api2, state, dispatch, broadcast, props, constants, vm,
+ getRules: getRules({ props, state }),
+ updateComputedLabelWidth: updateComputedLabelWidth(state),
+ removeValidateEvents: removeValidateEvents(vm),
+- unmounted: unmounted({ api: api2, vm, state }),
+- mounted: mounted({ api: api2, vm, props, state }),
++ registerField: registerField({ api: api2, vm, props, state }),
++ unregisterField: unregisterField({ api: api2, vm, state }),
++ unmounted: unmounted({ api: api2, state }),
++ mounted: mounted({ api: api2 }),
+ computedIsRequired: computedIsRequired({ api: api2, state }),
+ resetField: resetField({ api: api2, nextTick, props, state }),
+ getFilteredRule: getFilteredRule(api2),
+@@ -178,20 +185,32 @@ const initApi = ({ api: api2, state, dispatch, broadcast, props, constants, vm,
+ handleMouseleave: handleMouseleave(state)
+ });
+ };
+-const initWatch = ({ watch, api: api2, props, state }) => {
++const initWatch = ({ watch, api: api2, props, state, nextTick }) => {
+ watch(() => props.error, api2.watchError, { immediate: true });
+ watch(() => props.validateStatus, api2.watchValidateStatus);
+ watch(() => {
+ var _a;
+ return (_a = state.formInstance) == null ? void 0 : _a.displayOnly;
+ }, api2.clearDisplayedValue);
++ watch(
++ () => props.prop,
++ (newProp, oldProp) => {
++ if (oldProp) {
++ api2.unregisterField();
++ api2.clearValidate();
++ }
++ if (newProp) {
++ nextTick(() => api2.registerField());
++ }
++ }
++ );
+ };
+ const renderless = (props, { computed, inject, onMounted, onUnmounted, provide, reactive, watch }, { vm, constants, t, nextTick, broadcast, dispatch, mode, slots }) => {
+ const api2 = {};
+ const state = initState({ reactive, computed, api: api2, mode, inject, props });
+ provide("formItem", vm);
+ initApi({ api: api2, state, dispatch, broadcast, props, constants, vm, t, nextTick, slots });
+- initWatch({ watch, api: api2, props, state });
++ initWatch({ watch, api: api2, props, state, nextTick });
+ onMounted(api2.mounted);
+ vm.$on("displayed-value-changed", (param) => {
+ api2.getDisplayedValue(param);
+diff --git a/grid/utils/common.js b/grid/utils/common.js
+index a557e68633f95db4b162add9e31273ce81743282..012c24e94d49387bfd5b1d0506f5cffb60a21158 100644
+--- a/grid/utils/common.js
++++ b/grid/utils/common.js
+@@ -2,6 +2,7 @@ import {
+ __spreadValues
+ } from "../../chunk-G2ADBYYC.js";
+ import { isNull, find, isFunction } from "@opentiny/utils";
++import { isVue2 } from "@opentiny/vue-common";
+ import { get, set } from "../static";
+ const gridSize = ["medium", "small", "mini"];
+ const getSize = ({ size, $parent }) => size || ($parent && gridSize.includes($parent.size) ? $parent.size : null);
+@@ -116,7 +117,7 @@ const setCellValue = (row, column, value) => {
+ };
+ const hasChildrenList = (item) => item && item.children && item.children.length > 0;
+ const emitEvent = (vm, type, args) => {
+- if (vm.tableListeners[type]) {
++ if (resolveTableListeners(vm)[type]) {
+ const params = [].concat(args);
+ vm.$emit(type, ...params);
+ }
+@@ -144,16 +145,22 @@ const getListeners = ($attrs, $listeners) => {
+ const regHyphenate = /\B([A-Z])/g;
+ const regEventPrefix = /^on[A-Z]/;
+ const listeners = {};
+- if ($listeners) {
+- return $listeners;
++ if ($attrs) {
++ Object.keys($attrs).forEach((name) => {
++ const event = $attrs[name];
++ if (regEventPrefix.test(name) && typeof event === "function") {
++ listeners[name.slice(2).replace(regHyphenate, "-$1").toLowerCase()] = event;
++ }
++ });
+ }
+- Object.keys($attrs).forEach((name) => {
+- const event = $attrs[name];
+- if (regEventPrefix.test(name) && typeof event === "function") {
+- listeners[name.slice(2).replace(regHyphenate, "-$1").toLowerCase()] = event;
+- }
+- });
+- return listeners;
++ if (Object.keys(listeners).length) {
++ return listeners;
++ }
++ return $listeners || listeners;
++};
++const resolveTableListeners = (vm) => {
++ const gridListeners = vm.$grid ? getListeners(vm.$grid.$attrs, isVue2 ? vm.$grid.$listeners : undefined) : {};
++ return Object.assign({}, gridListeners, getListeners(vm.$attrs, isVue2 ? vm.$listeners : undefined));
+ };
+ function dfsCopy(tree, callback, parent = void 0, isTree = false, childrenKey = "children") {
+ let copy;
+@@ -190,6 +197,7 @@ export {
+ getFilters,
+ getFuncText,
+ getListeners,
++ resolveTableListeners,
+ getRowUniqueId,
+ getRowid,
+ getRowkey,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 54c61557..e2f96a8d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,9 +11,15 @@ patchedDependencies:
'@ai-sdk/openai-compatible@1.0.7':
hash: e9a77e12ec644839b6104591deb8c6b099c43fd4508f8f4fd4c1960635ac0be0
path: patches/@ai-sdk__openai-compatible@1.0.7.patch
- '@opentiny/ng-checkbox':
- hash: 8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6
- path: patches/@opentiny__ng-checkbox.patch
+ '@opentiny/vue-form-item@3.28.0':
+ hash: 0efe71be369a844388c7f28464c4b352cb43480c7fea7c457a96eb555ba5bd95
+ path: patches/@opentiny__vue-form-item@3.28.0.patch
+ '@opentiny/vue-grid@3.28.0':
+ hash: 5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0
+ path: patches/@opentiny__vue-grid@3.28.0.patch
+ '@opentiny/vue-renderless@3.28.2':
+ hash: eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd
+ path: patches/@opentiny__vue-renderless@3.28.2.patch
ai@6.0.116:
hash: 391ef8a5ea058148f60a34f00c8049ce6f4bcd4c0d14d4952bef7e5d9f0136d5
path: patches/ai@6.0.116.patch
@@ -31,19 +37,22 @@ importers:
'@opentiny/genui-sdk-angular':
specifier: workspace:*
version: link:../packages/frameworks/angular
+ '@opentiny/genui-sdk-materials-vue-opentiny-vue':
+ specifier: workspace:*
+ version: link:../packages/materials/vue-opentiny-vue
'@opentiny/genui-sdk-vue':
specifier: workspace:*
version: link:../packages/frameworks/vue
devDependencies:
vitepress:
specifier: ^1.6.3
- version: 1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3)
+ version: 1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3)
vitepress-demo-plugin:
specifier: ^1.4.1
- version: 1.5.1(shiki@2.5.0)(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
+ version: 1.5.1(shiki@2.5.0)(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
vitepress-plugin-tabs:
specifier: ^0.7.3
- version: 0.7.3(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
+ version: 0.7.3(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3))
packages/benchmarks:
dependencies:
@@ -131,7 +140,7 @@ importers:
specifier: ^0.7.3
version: 0.7.3
jsonrepair:
- specifier: ^3.13.3
+ specifier: 3.14.0
version: 3.14.0
radash:
specifier: ^12.1.1
@@ -190,7 +199,7 @@ importers:
version: 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
'@opentiny/ng':
specifier: ^1.0.3
- version: 1.0.3(d1fd79d4fe287fdf8b571535719c5978)
+ version: 1.0.3(455eb20ddee0d8f7a1b17d72e1dc5cca)
'@opentiny/ng-themes':
specifier: ^1.0.3
version: 1.0.3
@@ -225,6 +234,9 @@ importers:
'@opentiny/genui-sdk-core':
specifier: workspace:*
version: link:../../core
+ '@opentiny/genui-sdk-materials-angular-opentiny-ng':
+ specifier: workspace:*
+ version: link:../../materials/angular-opentiny-ng
'@opentiny/tiny-schema-renderer-ng':
specifier: workspace:*
version: link:../../../projects/tiny-schema-renderer-ng
@@ -306,9 +318,15 @@ importers:
packages/frameworks/vue:
dependencies:
+ '@opentiny/genui-sdk-core':
+ specifier: workspace:*
+ version: link:../../core
+ '@opentiny/genui-sdk-materials-vue-opentiny-vue':
+ specifier: workspace:*
+ version: link:../../materials/vue-opentiny-vue
'@opentiny/tiny-engine-builtin-component':
specifier: ^2.6.0
- version: 2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2)(@opentiny/vue@3.28.0)(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
+ version: 2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd))(@opentiny/vue@3.28.0)(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
'@opentiny/tiny-robot':
specifier: 0.3.3
version: 0.3.3(vue@3.5.26(typescript@5.9.3))
@@ -319,112 +337,16 @@ importers:
specifier: 0.3.3
version: 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/vue':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-button':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-card':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-carousel':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-carousel-item':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-chart-bar':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-histogram':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-line':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-pie':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-radar':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-ring':
- specifier: 3.14.0
- version: 3.14.0
- '@opentiny/vue-checkbox':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-checkbox-button':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-checkbox-group':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-col':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-date-picker':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-form':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-form-item':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-grid':
- specifier: ^3.28.0
+ specifier: ~3.28.0
version: 3.28.0
'@opentiny/vue-icon':
- specifier: ^3.28.0
+ specifier: ~3.28.0
version: 3.28.3
- '@opentiny/vue-input':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-layout':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-notify':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-numeric':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-radio':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-radio-group':
- specifier: ^3.28.0
- version: 3.28.0
'@opentiny/vue-renderless':
- specifier: ^3.28.2
- version: 3.28.2
- '@opentiny/vue-row':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-search':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-select':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-switch':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-tab-item':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-tabs':
- specifier: ^3.28.0
- version: 3.28.0
+ specifier: ~3.28.2
+ version: 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-transfer':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-tree':
- specifier: ^3.28.0
+ specifier: ~3.28.0
version: 3.28.0
uuid:
specifier: ^11.1.0
@@ -433,12 +355,6 @@ importers:
specifier: ^3.5.13
version: 3.5.26(typescript@5.9.3)
devDependencies:
- '@opentiny/genui-sdk-core':
- specifier: workspace:*
- version: link:../../core
- '@opentiny/genui-sdk-materials-vue-opentiny-vue':
- specifier: workspace:*
- version: link:../../materials/vue-opentiny-vue
'@opentiny/tiny-schema-renderer':
specifier: workspace:*
version: link:../../../projects/tiny-schema-renderer
@@ -471,6 +387,16 @@ importers:
version: 3.2.4(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
packages/materials/angular-opentiny-ng:
+ dependencies:
+ '@angular/core':
+ specifier: ^20.3.0
+ version: 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
+ '@opentiny/genui-sdk-core':
+ specifier: workspace:*
+ version: link:../../core
+ '@opentiny/ng':
+ specifier: ^1.0.3
+ version: 1.0.3(455eb20ddee0d8f7a1b17d72e1dc5cca)
devDependencies:
escape-string-regexp:
specifier: ^1.0.5
@@ -485,34 +411,161 @@ importers:
specifier: ^4.0.0
version: 4.5.4(@types/node@25.5.0)(rollup@4.54.0)(typescript@5.9.3)(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
+ packages/materials/vue-element-plus:
+ dependencies:
+ '@opentiny/genui-sdk-core':
+ specifier: workspace:*
+ version: link:../../core
+ devDependencies:
+ '@vitejs/plugin-vue':
+ specifier: ^5.0.0
+ version: 5.2.4(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
+ '@vue/tsconfig':
+ specifier: ^0.8.1
+ version: 0.8.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))
+ element-plus:
+ specifier: ^2.9.0
+ version: 2.14.0(vue@3.5.26(typescript@5.9.3))
+ escape-string-regexp:
+ specifier: ^1.0.5
+ version: 1.0.5
+ typescript:
+ specifier: ^5.8.2
+ version: 5.9.3
+ vite:
+ specifier: ^6.0.0
+ version: 6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
+ vite-plugin-css-injected-by-js:
+ specifier: ^3.5.2
+ version: 3.5.2(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
+ vite-plugin-dts:
+ specifier: ^4.0.0
+ version: 4.5.4(@types/node@25.5.0)(rollup@4.54.0)(typescript@5.9.3)(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
+ vitest:
+ specifier: ^3.0.0
+ version: 3.2.4(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
+ vue:
+ specifier: ^3.5.13
+ version: 3.5.26(typescript@5.9.3)
+
packages/materials/vue-opentiny-vue:
dependencies:
+ '@opentiny/genui-sdk-core':
+ specifier: workspace:*
+ version: link:../../core
'@opentiny/vue-button':
- specifier: ^3.28.0
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-card':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-carousel':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-carousel-item':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-checkbox':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-checkbox-button':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-checkbox-group':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-col':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-date-picker':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-form':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-form-item':
+ specifier: ~3.28.0
+ version: 3.28.0(patch_hash=0efe71be369a844388c7f28464c4b352cb43480c7fea7c457a96eb555ba5bd95)
+ '@opentiny/vue-grid':
+ specifier: ~3.28.0
+ version: 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
+ '@opentiny/vue-huicharts-bar':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-funnel':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-gauge':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-graph':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-histogram':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-line':
+ specifier: 3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-pie':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-process':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-radar':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-ring':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-scatter':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-huicharts-waterfall':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-input':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-layout':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-numeric':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-pager':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-radio':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-radio-group':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-row':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-search':
+ specifier: ~3.28.0
version: 3.28.0
- '@opentiny/vue-chart-bar':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-histogram':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-line':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-pie':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-radar':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-ring':
- specifier: 3.14.0
- version: 3.14.0
'@opentiny/vue-select':
- specifier: ^3.28.0
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-switch':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-tab-item':
+ specifier: ~3.28.0
version: 3.28.0
'@opentiny/vue-tabs':
- specifier: ^3.28.0
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-transfer':
+ specifier: ~3.28.0
+ version: 3.28.0
+ '@opentiny/vue-tree':
+ specifier: ~3.28.0
version: 3.28.0
gridstack:
specifier: ^12.4.2
@@ -545,6 +598,9 @@ importers:
packages/server:
dependencies:
+ '@opentiny/genui-sdk-core':
+ specifier: workspace:*
+ version: link:../core
commander:
specifier: ^14.0.0
version: 14.0.2
@@ -567,9 +623,6 @@ importers:
'@opentiny/genui-sdk-chat-completions':
specifier: workspace:*
version: link:../chat-completions
- '@opentiny/genui-sdk-core':
- specifier: workspace:*
- version: link:../core
'@types/commander':
specifier: ^2.12.2
version: 2.12.5
@@ -605,7 +658,7 @@ importers:
version: 7.18.13
'@opentiny/tiny-engine-builtin-component':
specifier: ^2.6.0
- version: 2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2)(@opentiny/vue@3.28.0)(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))(vue@3.5.26(typescript@5.9.3))
+ version: 2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.30.0)(@opentiny/vue@3.28.0)(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))(vue@3.5.26(typescript@5.9.3))
'@vue/babel-plugin-jsx':
specifier: ^1.2.5
version: 1.5.0(@babel/core@7.18.13)
@@ -625,111 +678,18 @@ importers:
'@babel/standalone':
specifier: ^7.23.0
version: 7.28.5
- '@opentiny/vue-button':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-card':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-carousel':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-carousel-item':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-chart-bar':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-histogram':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-line':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-pie':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-radar':
- specifier: ~3.14.0
- version: 3.14.0
- '@opentiny/vue-chart-ring':
- specifier: 3.14.0
- version: 3.14.0
- '@opentiny/vue-checkbox':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-checkbox-button':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-checkbox-group':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-col':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-date-picker':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-form':
+ '@opentiny/vue':
specifier: ^3.28.0
version: 3.28.0
- '@opentiny/vue-form-item':
+ '@opentiny/vue-huicharts':
specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-grid':
- specifier: ^3.28.0
- version: 3.28.0
+ version: 3.28.0(echarts@5.4.1)
'@opentiny/vue-icon':
specifier: ^3.28.0
version: 3.28.3
- '@opentiny/vue-input':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-layout':
- specifier: ^3.28.0
- version: 3.28.0
'@opentiny/vue-notify':
specifier: ^3.28.0
version: 3.28.0
- '@opentiny/vue-numeric':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-radio':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-radio-group':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-renderless':
- specifier: ^3.28.2
- version: 3.28.2
- '@opentiny/vue-row':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-search':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-select':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-switch':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-tab-item':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-tabs':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-theme':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-transfer':
- specifier: ^3.28.0
- version: 3.28.0
- '@opentiny/vue-tree':
- specifier: ^3.28.0
- version: 3.28.0
'@vitejs/plugin-vue':
specifier: ^5.1.2
version: 5.2.4(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))(vue@3.5.26(typescript@5.9.3))
@@ -781,12 +741,6 @@ importers:
'@angular/router':
specifier: ^20.3.0
version: 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
- '@opentiny/ng':
- specifier: ^1.0.3
- version: 1.0.3(d1fd79d4fe287fdf8b571535719c5978)
- '@opentiny/ng-themes':
- specifier: ^1.0.3
- version: 1.0.3
lodash:
specifier: 4.17.21
version: 4.17.21
@@ -815,6 +769,12 @@ importers:
'@angular/compiler-cli':
specifier: ^20.3.0
version: 20.3.15(@angular/compiler@20.3.15)(typescript@5.9.3)
+ '@opentiny/ng':
+ specifier: ^1.0.3
+ version: 1.0.3(455eb20ddee0d8f7a1b17d72e1dc5cca)
+ '@opentiny/ng-themes':
+ specifier: ^1.0.3
+ version: 1.0.3
'@types/jasmine':
specifier: ~5.1.0
version: 5.1.13
@@ -856,7 +816,7 @@ importers:
version: 1.1.0(typescript@5.9.3)(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
'@opentiny/tiny-robot-svgs':
specifier: ^0.3.3
- version: 0.3.3(vue@3.4.38(typescript@5.9.3))
+ version: 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/vue':
specifier: ~3.28.0
version: 3.28.0
@@ -879,8 +839,8 @@ importers:
specifier: ^11.5.1
version: 11.11.1
vue:
- specifier: ~3.4.32
- version: 3.4.38(typescript@5.9.3)
+ specifier: ^3.5.18
+ version: 3.5.26(typescript@5.9.3)
devDependencies:
'@opentiny/vue-vite-import':
specifier: ^1.2.0
@@ -890,10 +850,10 @@ importers:
version: 17.0.45
'@vitejs/plugin-vue':
specifier: ^6.0.1
- version: 6.0.3(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.4.38(typescript@5.9.3))
+ version: 6.0.3(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
'@vue/tsconfig':
specifier: ^0.8.1
- version: 0.8.1(typescript@5.9.3)(vue@3.4.38(typescript@5.9.3))
+ version: 0.8.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))
less:
specifier: ^4.1.3
version: 4.5.1
@@ -918,9 +878,9 @@ importers:
sites/playground/schema-renderer-ng-adpater:
dependencies:
- '@opentiny/tiny-schema-renderer-ng':
+ '@opentiny/genui-sdk-angular':
specifier: workspace:*
- version: link:../../../projects/tiny-schema-renderer-ng
+ version: link:../../../packages/frameworks/angular
vue:
specifier: ^3.5.26
version: 3.5.26(typescript@5.9.3)
@@ -943,6 +903,12 @@ importers:
sites/playground/server:
dependencies:
+ '@a2a-js/sdk':
+ specifier: ^0.3.13
+ version: 0.3.13(express@5.2.1)
+ '@a2a-js/sdk-v1':
+ specifier: npm:@a2a-js/sdk@^1.0.0-alpha.0
+ version: '@a2a-js/sdk@1.0.0-beta.0(express@5.2.1)'
'@ai-sdk/anthropic':
specifier: ^2.0.5
version: 2.0.57(zod@3.25.76)
@@ -952,6 +918,9 @@ importers:
'@ai-sdk/openai':
specifier: ^2.0.10
version: 2.0.89(zod@3.25.76)
+ '@apidevtools/swagger-parser':
+ specifier: ^12.1.0
+ version: 12.1.0(openapi-types@12.1.3)
'@modelcontextprotocol/sdk':
specifier: ^1.13.0
version: 1.24.0(zod@3.25.76)
@@ -985,15 +954,18 @@ importers:
express-ws:
specifier: ^5.0.2
version: 5.0.2(express@5.2.1)
- extensionless:
- specifier: ^1.9.9
- version: 1.9.9
+ js-yaml:
+ specifier: ^4.1.1
+ version: 4.3.0
json-schema-to-zod:
specifier: ^2.6.1
version: 2.7.0
minimist:
specifier: ^1.2.8
version: 1.2.8
+ openapi-types:
+ specifier: ^12.1.3
+ version: 12.1.3
raw-body:
specifier: ^3.0.0
version: 3.0.2
@@ -1019,6 +991,9 @@ importers:
'@types/express-ws':
specifier: ^3.0.5
version: 3.0.6
+ '@types/js-yaml':
+ specifier: ^4.0.9
+ version: 4.0.9
'@types/ws':
specifier: ^8.18.1
version: 8.18.1
@@ -1044,40 +1019,43 @@ importers:
specifier: ^20.0.0
version: 20.19.27
typescript:
- specifier: ~5.8.3
- version: 5.8.3
+ specifier: ^5.9.3
+ version: 5.9.3
sites/playground/web:
dependencies:
'@opentiny/genui-sdk-core':
specifier: workspace:*
version: link:../../../packages/core
+ '@opentiny/genui-sdk-materials-vue-opentiny-vue':
+ specifier: workspace:*
+ version: link:../../../packages/materials/vue-opentiny-vue
'@opentiny/genui-sdk-vue':
specifier: workspace:*
version: link:../../../packages/frameworks/vue
'@opentiny/tiny-robot':
specifier: 0.3.3
- version: 0.3.3(vue@3.5.26(typescript@5.8.3))
+ version: 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/tiny-robot-kit':
specifier: 0.3.3
- version: 0.3.3(vue@3.5.26(typescript@5.8.3))
+ version: 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/tiny-robot-svgs':
specifier: 0.3.3
- version: 0.3.3(vue@3.5.26(typescript@5.8.3))
+ version: 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/vue':
- specifier: ^3.28.0
+ specifier: ~3.28.0
version: 3.28.0
'@opentiny/vue-directive':
specifier: ^3.28.0
version: 3.28.0
'@opentiny/vue-icon':
- specifier: ^3.28.0
+ specifier: ~3.28.0
version: 3.28.3
'@opentiny/vue-renderless':
- specifier: ^3.28.2
- version: 3.29.0
+ specifier: ~3.28.2
+ version: 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme':
- specifier: ^3.28.0
+ specifier: ~3.28.0
version: 3.28.0
ai:
specifier: 6.0.116
@@ -1087,7 +1065,7 @@ importers:
version: 4.0.1
monaco-editor-vue3:
specifier: ^1.0.4
- version: 1.0.5(monaco-editor@0.55.1)(vue@3.5.26(typescript@5.8.3))
+ version: 1.0.5(monaco-editor@0.55.1)(vue@3.5.26(typescript@5.9.3))
schema-renderer-ng-adpater:
specifier: workspace:*
version: link:../schema-renderer-ng-adpater
@@ -1099,14 +1077,14 @@ importers:
version: link:../vite-commit-hash-plugin
vue:
specifier: ^3.5.18
- version: 3.5.26(typescript@5.8.3)
+ version: 3.5.26(typescript@5.9.3)
devDependencies:
'@vitejs/plugin-vue':
specifier: ^6.0.1
- version: 6.0.3(vite@7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.8.3))
+ version: 6.0.3(vite@7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
'@vue/tsconfig':
specifier: ^0.7.0
- version: 0.7.0(typescript@5.8.3)(vue@3.5.26(typescript@5.8.3))
+ version: 0.7.0(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))
gridstack:
specifier: ^12.2.1
version: 12.4.2
@@ -1114,8 +1092,8 @@ importers:
specifier: ^0.7.3
version: 0.7.3
typescript:
- specifier: ~5.8.3
- version: 5.8.3
+ specifier: ^5.9.3
+ version: 5.9.3
vite:
specifier: ^7.1.2
version: 7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
@@ -1127,10 +1105,40 @@ importers:
version: 0.24.0(rollup@4.54.0)(vite@7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
vue-tsc:
specifier: ^3.0.5
- version: 3.2.1(typescript@5.8.3)
+ version: 3.2.1(typescript@5.9.3)
packages:
+ '@a2a-js/sdk@0.3.13':
+ resolution: {integrity: sha512-BZr0f9JVNQs3GKOM9xINWCh6OKIJWZFPyqqVqTym5mxO2Eemc6I/0zL7zWnljHzGdaf5aZQyQN5xa6PSH62q+A==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@bufbuild/protobuf': ^2.10.2
+ '@grpc/grpc-js': ^1.11.0
+ express: ^4.21.2 || ^5.1.0
+ peerDependenciesMeta:
+ '@bufbuild/protobuf':
+ optional: true
+ '@grpc/grpc-js':
+ optional: true
+ express:
+ optional: true
+
+ '@a2a-js/sdk@1.0.0-beta.0':
+ resolution: {integrity: sha512-1k2GJdATg0ZJMNVD0jqox+oE5teUaUbJWx5ooSW2i3hA/B00Ev6kK3hZuxcsoZYbYvp8eAyppU3rvjTpglzdcg==}
+ engines: {node: '>=20'}
+ peerDependencies:
+ '@bufbuild/protobuf': ^2.10.2
+ '@grpc/grpc-js': ^1.11.0
+ express: ^4.21.2 || ^5.1.0
+ peerDependenciesMeta:
+ '@bufbuild/protobuf':
+ optional: true
+ '@grpc/grpc-js':
+ optional: true
+ express:
+ optional: true
+
'@ai-sdk/anthropic@2.0.57':
resolution: {integrity: sha512-DREpYqW2pylgaj69gZ+K8u92bo9DaMgFdictYnY+IwYeY3bawQ4zI7l/o1VkDsBDljAx8iYz5lPURwVZNu+Xpg==}
engines: {node: '>=18'}
@@ -1315,6 +1323,7 @@ packages:
'@angular/animations@20.3.15':
resolution: {integrity: sha512-ikyKfhkxoqQA6JcBN0B9RaN6369sM1XYX81Id0lI58dmWCe7gYfrTp8ejqxxKftl514psQO3pkW8Gn1nJ131Gw==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+ deprecated: '@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.'
peerDependencies:
'@angular/core': 20.3.15
@@ -1473,6 +1482,22 @@ packages:
'@angular/platform-browser': 20.3.15
rxjs: ^6.5.3 || ^7.4.0
+ '@apidevtools/json-schema-ref-parser@14.0.1':
+ resolution: {integrity: sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw==}
+ engines: {node: '>= 16'}
+
+ '@apidevtools/openapi-schemas@2.1.0':
+ resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==}
+ engines: {node: '>=10'}
+
+ '@apidevtools/swagger-methods@3.0.2':
+ resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==}
+
+ '@apidevtools/swagger-parser@12.1.0':
+ resolution: {integrity: sha512-e5mJoswsnAX0jG+J09xHFYQXb/bUc5S3pLpMxUuRUA2H8T2kni3yEoyz2R3Dltw5f4A6j6rPNMpWTK+iVDFlng==}
+ peerDependencies:
+ openapi-types: '>=7'
+
'@babel/code-frame@7.27.1':
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
@@ -1620,6 +1645,10 @@ packages:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
+ '@ctrl/tinycolor@4.2.0':
+ resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==}
+ engines: {node: '>=14'}
+
'@cush/relative@1.0.0':
resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==}
@@ -1649,6 +1678,11 @@ packages:
search-insights:
optional: true
+ '@element-plus/icons-vue@2.3.2':
+ resolution: {integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==}
+ peerDependencies:
+ vue: ^3.2.0
+
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'}
@@ -2735,6 +2769,9 @@ packages:
'@opentiny/genui-sdk-vue@1.1.0':
resolution: {integrity: sha512-08H0fc274qlW6LmrzdNyBhjv92vjGiKlOahrwBOCM54wWPSD2dDJhX6aBxyz4nrWE3vZ/ifYwW6USDWZTW6f2g==}
+ '@opentiny/huicharts@1.0.1':
+ resolution: {integrity: sha512-KsVNZwCstMJec2vM/uMff9jj/nNHXCchiwGGU4+MGP1nRwg7Hkj8pjgJQh/tJR6+AEKPY/h+TewRM3S6KBtn5g==}
+
'@opentiny/ng-accordion@1.0.3':
resolution: {integrity: sha512-45v5Is3bF+SVjQhCu7StEfHAvAR5oZLjQXoYds1KRzLZk7u6EyOikW5m4XKmi8/8vplU+NlCQZZ5/5jh2HZBPQ==}
peerDependencies:
@@ -3981,8 +4018,8 @@ packages:
'@opentiny/utils@3.28.0':
resolution: {integrity: sha512-bHIP634NnFZQELILkD4q/Jg7SfpB32PYEPs+MUGcLaOdf//u2CCXF5rK3BoWnguTx2+bwdPalaoFOTR6QP0Zwg==}
- '@opentiny/utils@3.29.0':
- resolution: {integrity: sha512-D4n2F0Vdnus4+S/DH7tigiGZp2yAU91PWX2hMSLtkzQd6KKgW0dMde/32O0JS0R/AJdnCBw//bg5LUdG4zjx9A==}
+ '@opentiny/utils@3.30.0':
+ resolution: {integrity: sha512-b330KsReSErdisbGnWuFFY8ZQrSDfiD474n2+iyqoHdFOP4INxK1xRn3yT5SC/f9HIsovVnSPdztIEWE3EwGwQ==}
'@opentiny/vue-action-menu@3.28.0':
resolution: {integrity: sha512-trAOFhMCfhILpigTm4jjPALR2MuE4nshOM6ML+UpvCpPKAnOvAdy5tcPBPeAwJuxg0+I18uUpHhbvTa7J+QtIQ==}
@@ -4278,12 +4315,87 @@ packages:
'@opentiny/vue-hooks@3.28.0':
resolution: {integrity: sha512-XCsQxoHBkdCCGII+FZay0f83Jc3mbRb/gMtO0oqCK+SyseW87KtlSiGFS3WfRWx5pLFgsM80tcKLjkXarJTiTw==}
- '@opentiny/vue-hooks@3.29.0':
- resolution: {integrity: sha512-GPtCGsHG63/0DPr2qhUSyVq/u/uo3htIb5f5pKOHsdeq3xRgoRlV+rIARDraSCrptfrX2fOGlgZz+wyrMd6YjA==}
+ '@opentiny/vue-hooks@3.30.0':
+ resolution: {integrity: sha512-WcpEjaiuJcg4RDEJSdCz3wTktGczefAcsnBQTN99q5FPoPXtGoJ+W17ZVQnV2RFNUJPqRJyax7E/Ij07gnCEng==}
'@opentiny/vue-hrapprover@3.28.0':
resolution: {integrity: sha512-4mP8hOQ5TOxVEZKV82UmUWT+8eRHl+a5DlLCBYJT2CisZ463LQ/DjqieWTJplgxf258w96pc+t0PaNxklLl5QQ==}
+ '@opentiny/vue-huicharts-amap@3.28.0':
+ resolution: {integrity: sha512-bf1LmfV34iOEOQ+FkHyp14AlnSxcJPccwyFcbaT/0j/6wFPeuuHOoK8f6KepGqUTGkQxMLZkNYcajugEmLHz3w==}
+
+ '@opentiny/vue-huicharts-bar@3.28.0':
+ resolution: {integrity: sha512-Iav5Wrw5AZ5ZK5AL9iiMNDo+1j5c0eVQTN7o6KiMdWb2AWG3EszJgbNve75fmMotY30e9PmLMNGOaQgDYf7LxQ==}
+
+ '@opentiny/vue-huicharts-bmap@3.28.0':
+ resolution: {integrity: sha512-b4nvD/VCVATS7LkNnG6kHA4BAm6mksLwCWywaz79vzBOYzdbwhLk/Zi6TPH4nkXSdEXK5Y+4K/g74cYghq86Nw==}
+
+ '@opentiny/vue-huicharts-boxplot@3.28.0':
+ resolution: {integrity: sha512-euy39q9OEWQWHpCOuU1VH0fcnAs/p9ooLL2CK3TdXHILZzLCC6VqjHPhzTE99cZZsp8HML2Beh3RFdIkZ7xbSA==}
+
+ '@opentiny/vue-huicharts-candle@3.28.0':
+ resolution: {integrity: sha512-H38UW67jtyRV8YYPtupZTvpKRVfarTVeNnyd2TiY89/AI2L5xLnXUUICwo330NFXgUX45oAD+dWQDUzWCAWcQw==}
+
+ '@opentiny/vue-huicharts-core@3.28.0':
+ resolution: {integrity: sha512-fExjw4kJDGSdoNvNwAP/7hze56mED6UdUGay4oTjv1kPQwd/u/J0HHDy+9/lvvOSxNJ7zd3hU+PBK3ynPubCcA==}
+
+ '@opentiny/vue-huicharts-funnel@3.28.0':
+ resolution: {integrity: sha512-Gq+rA7CQFFfbnDqa/1tRLL5P8jiX6s0fRQKdpQiI759lmiCVyei8nxkTNZzHqPMIesS++HZuvsY5Oi0xQSQ6iQ==}
+
+ '@opentiny/vue-huicharts-gauge@3.28.0':
+ resolution: {integrity: sha512-YvZ8JxqTdC8Wxsy9dNopalcZkqJZkGQchD1UwAPdZ+kCqWBjZPtk29Bzl8fi6Z7v5zdCTfxHhH34o3G1nprNiw==}
+
+ '@opentiny/vue-huicharts-graph@3.28.0':
+ resolution: {integrity: sha512-uoOTVk2/feZpN2ZexSCs3i+AAmCfn90OeU1oHo9AVxtkqKpn0z3er1j6lXpNkUm2QaBLlj5B0hP6jg4MTfmAgg==}
+
+ '@opentiny/vue-huicharts-heatmap@3.28.0':
+ resolution: {integrity: sha512-Jl8dCad+fKWdZY4LDfZG0Q8Q30GmD9mt/f2LkL5FLdzdDmT8FL13XBhuTbf/lTNuEetcC3fue2BUGVUbvq0KSA==}
+
+ '@opentiny/vue-huicharts-histogram@3.28.0':
+ resolution: {integrity: sha512-l4F5A2HdcKS7AtlZrzj8pS8J2A/HOiRI5X99F2qPoauKLtw+oeHZEf/eP+yX3c6xwA39EStMLRlxT5cgUja9RQ==}
+
+ '@opentiny/vue-huicharts-line@3.28.0':
+ resolution: {integrity: sha512-QIrjs1bBuNo1pSEhBzVwYFJ0rMd5CpdlzNQ7tLuEOy8xa0/CqE81MAqNNru/sfBiZJUUEkVaRCeb+HNMhoWAIA==}
+
+ '@opentiny/vue-huicharts-liquidfill@3.28.0':
+ resolution: {integrity: sha512-eC5PnWnDV+naU3k0AzpOtwlbrvjwgxIulI0xJXVVcal6xXbNEvJwT+T2/4MlpTSNB7V5oepcb11VY+eJhX+xyw==}
+
+ '@opentiny/vue-huicharts-map@3.28.0':
+ resolution: {integrity: sha512-Ot+BMWGLXFPxLlPLf3EJXiF8yHcHicoIm9VODC0dtEBlF6szJ9SN6zUHrhn3ihReL1lrpyTbdIIglttREwl6gg==}
+
+ '@opentiny/vue-huicharts-pie@3.28.0':
+ resolution: {integrity: sha512-xUK0Ubhp7ZjLAunufaNcKDxhMeNKXWvDPz6CsixfjjCTFvbxzaGWvPpGNU3wowBDKkWcsT/KDBL52KNbY2Wtow==}
+
+ '@opentiny/vue-huicharts-process@3.28.0':
+ resolution: {integrity: sha512-EoImG7J7Be6OjnbTn8j5fadPWoBcPIX+MEEpplZo5z9KzYSIgA+k+46U6luHGiMN8Ki8CflngQuJyX7N3u2ehA==}
+
+ '@opentiny/vue-huicharts-radar@3.28.0':
+ resolution: {integrity: sha512-eqVPNA8DioT4bisNLEByupFVLpV0wpNcx8rKDPNokKwjBt2JDy+0BpSfvWNeje7HR3j+arCDLvdEI0xBTEX1lw==}
+
+ '@opentiny/vue-huicharts-ring@3.28.0':
+ resolution: {integrity: sha512-K3qG73AQsOC8+xSJaA5/U5s6z88AUOfV+aJtDHEfn3RgJWMzVcJJM+29m1VOxISTcIekwxosGvTiPiTsihyKwQ==}
+
+ '@opentiny/vue-huicharts-sankey@3.28.0':
+ resolution: {integrity: sha512-gQVoNjCfu35PGB5685TveL7WDwFZGfemL8czNULM7YPqwUg5PlxTG4q/3n/qUBfseciyfEH1mQsi0DD0mTQTbQ==}
+
+ '@opentiny/vue-huicharts-scatter@3.28.0':
+ resolution: {integrity: sha512-GqWVioZKj3RLOjoRkiHXFWLf1J/dZ3T/Fqy7R/PHxqt0JYfjHoUzc+jr7wMDKHojNO6JR051NRxLHJgkCOm+ZA==}
+
+ '@opentiny/vue-huicharts-sunburst@3.28.0':
+ resolution: {integrity: sha512-pj/6+1cKWInroRVJFmFoESdSs4SVBuG3GzswNRJnjv1NmqRvPq3bonUjbQjxHxB3qieBXvIHnHaHLSvrUhY+TA==}
+
+ '@opentiny/vue-huicharts-tree@3.28.0':
+ resolution: {integrity: sha512-MSfFvB+oZxVUO7ngO9zmuy8TN3Ck75XmITupa7J37M7Uzhvwvn9T2F5S+k1M9fnHXIjR2kP2aiMinw2dJjdMXw==}
+
+ '@opentiny/vue-huicharts-waterfall@3.28.0':
+ resolution: {integrity: sha512-yc6rhul03vAtzSyMMLUbYFd2PsCn6wEH7tA93w/xKxSJA4vKj3NUseIE0LbrSlSLWmcO208JYUlFCrmDthZMkg==}
+
+ '@opentiny/vue-huicharts-wordcloud@3.28.0':
+ resolution: {integrity: sha512-iU7M/QqnPbiS5tytjQlpwlFReVmsmCiWXTEdvsQiafYU1KJ+aKlKFmBRN3AXxs55SHYbUsBm/Yr4CdKXAKfcAw==}
+
+ '@opentiny/vue-huicharts@3.28.0':
+ resolution: {integrity: sha512-syBeU7v0oq7z7tOKNH71jC513PHequ9ONwyIuVbAlvIWqXfmLqf4paSj+T7MyUwuD6W03YGMviu7BUv9psDXxw==}
+
'@opentiny/vue-icon@3.28.3':
resolution: {integrity: sha512-gOmR/2m9aEKH26jvCDBtiUtb1DDvjmFX8tn4gKK+Fd32M9HYMyZaZpNPvYrK33/GLSUWIDXUJOmeypnSyOJWog==}
@@ -4434,8 +4546,8 @@ packages:
'@opentiny/vue-renderless@3.28.2':
resolution: {integrity: sha512-fCTQ5lWTbaTCjBM2x+dddEbMCG0w70HPNfs0fT+vw0OPigKbQPQld9+nLvXyiRM56miBBfLeWkKJJgchFtkzEA==}
- '@opentiny/vue-renderless@3.29.0':
- resolution: {integrity: sha512-Xp14idgz533HeQI8wDOEhvXVwddaOwWw+Fr6Hfxy85Lrws+cHpj6vUTIo+Uvw785Kne2e/5JvKdKDAZ3YXUvjg==}
+ '@opentiny/vue-renderless@3.30.0':
+ resolution: {integrity: sha512-rY3S3PqzDa2W3ZY8K+OiXokcFHLvXzVchG0DYUQCOwZGoLs7S+vcbSFMKyCOxp4siWXO0RLAdEkHQoeX1i7VxQ==}
'@opentiny/vue-river@3.28.0':
resolution: {integrity: sha512-3+jTIIW5N8439hDUjLneOL7jn+0oO1FWq+bRoZCqN/qtkNIsRbD10d3g+C5OffmjGdslUlMKjmYTfCva3lMpHw==}
@@ -5113,6 +5225,9 @@ packages:
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+ '@sxzz/popperjs-es@2.11.8':
+ resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==}
+
'@trysound/sax@0.2.0':
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
engines: {node: '>=10.13.0'}
@@ -5198,6 +5313,12 @@ packages:
'@types/jasmine@5.1.13':
resolution: {integrity: sha512-MYCcDkruFc92LeYZux5BC0dmqo2jk+M5UIZ4/oFnAPCXN9mCcQhLyj7F3/Za7rocVyt5YRr1MmqJqFlvQ9LVcg==}
+ '@types/js-yaml@4.0.9':
+ resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==}
+
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
@@ -5207,9 +5328,15 @@ packages:
'@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
+ '@types/lodash-es@4.17.12':
+ resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+
'@types/lodash@4.17.21':
resolution: {integrity: sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==}
+ '@types/lodash@4.17.24':
+ resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==}
+
'@types/markdown-it@14.1.2':
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
@@ -5352,27 +5479,15 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
- '@vue/compiler-core@3.4.38':
- resolution: {integrity: sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==}
-
'@vue/compiler-core@3.5.26':
resolution: {integrity: sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==}
- '@vue/compiler-dom@3.4.38':
- resolution: {integrity: sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==}
-
'@vue/compiler-dom@3.5.26':
resolution: {integrity: sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==}
- '@vue/compiler-sfc@3.4.38':
- resolution: {integrity: sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==}
-
'@vue/compiler-sfc@3.5.26':
resolution: {integrity: sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==}
- '@vue/compiler-ssr@3.4.38':
- resolution: {integrity: sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==}
-
'@vue/compiler-ssr@3.5.26':
resolution: {integrity: sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==}
@@ -5399,37 +5514,20 @@ packages:
'@vue/language-core@3.2.1':
resolution: {integrity: sha512-g6oSenpnGMtpxHGAwKuu7HJJkNZpemK/zg3vZzZbJ6cnnXq1ssxuNrXSsAHYM3NvH8p4IkTw+NLmuxyeYz4r8A==}
- '@vue/reactivity@3.4.38':
- resolution: {integrity: sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==}
-
'@vue/reactivity@3.5.26':
resolution: {integrity: sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==}
- '@vue/runtime-core@3.4.38':
- resolution: {integrity: sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==}
-
'@vue/runtime-core@3.5.26':
resolution: {integrity: sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==}
- '@vue/runtime-dom@3.4.38':
- resolution: {integrity: sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==}
-
'@vue/runtime-dom@3.5.26':
resolution: {integrity: sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==}
- '@vue/server-renderer@3.4.38':
- resolution: {integrity: sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==}
- peerDependencies:
- vue: 3.4.38
-
'@vue/server-renderer@3.5.26':
resolution: {integrity: sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==}
peerDependencies:
vue: 3.5.26
- '@vue/shared@3.4.38':
- resolution: {integrity: sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==}
-
'@vue/shared@3.5.26':
resolution: {integrity: sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==}
@@ -5463,6 +5561,11 @@ packages:
peerDependencies:
vue: ^3.5.0
+ '@vueuse/core@14.3.0':
+ resolution: {integrity: sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==}
+ peerDependencies:
+ vue: ^3.5.0
+
'@vueuse/integrations@12.8.2':
resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==}
peerDependencies:
@@ -5510,6 +5613,9 @@ packages:
'@vueuse/metadata@13.9.0':
resolution: {integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==}
+ '@vueuse/metadata@14.3.0':
+ resolution: {integrity: sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==}
+
'@vueuse/shared@12.8.2':
resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==}
@@ -5518,6 +5624,11 @@ packages:
peerDependencies:
vue: ^3.5.0
+ '@vueuse/shared@14.3.0':
+ resolution: {integrity: sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==}
+ peerDependencies:
+ vue: ^3.5.0
+
'@yarnpkg/lockfile@1.1.0':
resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==}
@@ -5543,6 +5654,11 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ acorn@8.17.0:
+ resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
adler-32@1.3.1:
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
engines: {node: '>=0.8'}
@@ -5674,6 +5790,9 @@ packages:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
+ async-validator@4.2.5:
+ resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
+
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@@ -5841,6 +5960,9 @@ packages:
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
+ call-me-maybe@1.0.2:
+ resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
+
camel-case@4.1.2:
resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
@@ -6167,6 +6289,9 @@ packages:
resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==}
engines: {node: '>=4.0'}
+ dayjs@1.11.20:
+ resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==}
+
de-indent@1.0.2:
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
@@ -6356,6 +6481,16 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ echarts-liquidfill@3.1.0:
+ resolution: {integrity: sha512-5Dlqs/jTsdTUAsd+K5LPLLTgrbbNORUSBQyk8PSy1Mg2zgHDWm83FmvA4s0ooNepCJojFYRITTQ4GU1UUSKYLw==}
+ peerDependencies:
+ echarts: ^5.0.1
+
+ echarts-wordcloud@2.0.0:
+ resolution: {integrity: sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==}
+ peerDependencies:
+ echarts: ^5.0.1
+
echarts@5.4.1:
resolution: {integrity: sha512-9ltS3M2JB0w2EhcYjCdmtrJ+6haZcW6acBolMGIuf01Hql1yrIV01L1aRj7jsaaIULJslEP9Z3vKlEmnJaWJVQ==}
@@ -6365,6 +6500,11 @@ packages:
electron-to-chromium@1.5.267:
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
+ element-plus@2.14.0:
+ resolution: {integrity: sha512-POgH+TtoreaEKWqYYAVQyE6i8rQMEFqAEublyF29dBA5yASWPLKY6EzfeqBTr2Uv26mPss4vSrMrNPyaK7LX5w==}
+ peerDependencies:
+ vue: ^3.3.7
+
elliptic@6.6.1:
resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==}
@@ -6716,9 +6856,6 @@ packages:
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
- extensionless@1.9.9:
- resolution: {integrity: sha512-fz0cWfLA4pgc2nwmg6lc2UH+g+NlFuD63VWqp8n1wGAZSSbPNoARkA54BxXRjYCYW9LvhBnA3NyJaGS2KudkWw==}
-
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -6980,11 +7117,12 @@ packages:
glob@10.5.0:
resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
hasBin: true
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
- deprecated: Glob versions prior to v9 are no longer supported
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
globby@10.0.2:
resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==}
@@ -7443,6 +7581,9 @@ packages:
jose@6.1.3:
resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==}
+ jose@6.2.3:
+ resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==}
+
jpegtran-bin@5.0.2:
resolution: {integrity: sha512-4FSmgIcr8d5+V6T1+dHbPZjaFH0ogVyP4UVsE+zri7S9YLO4qAT2our4IN3sW3STVgNTbqPermdIgt2XuAJ4EA==}
engines: {node: '>=10'}
@@ -7459,6 +7600,10 @@ packages:
js-tokens@9.0.1:
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+ js-yaml@4.3.0:
+ resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==}
+ hasBin: true
+
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@@ -7588,6 +7733,16 @@ packages:
lodash-es@4.17.22:
resolution: {integrity: sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==}
+ lodash-es@4.18.1:
+ resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
+
+ lodash-unified@1.0.3:
+ resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==}
+ peerDependencies:
+ '@types/lodash-es': '*'
+ lodash: '*'
+ lodash-es: '*'
+
lodash.clonedeep@4.5.0:
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
@@ -7598,6 +7753,9 @@ packages:
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ lodash@4.18.1:
+ resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
+
log-symbols@6.0.0:
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
engines: {node: '>=18'}
@@ -7724,6 +7882,9 @@ packages:
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
engines: {node: '>= 0.8'}
+ memoize-one@6.0.0:
+ resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
+
meow@3.7.0:
resolution: {integrity: sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==}
engines: {node: '>=0.10.0'}
@@ -8001,6 +8162,9 @@ packages:
resolution: {integrity: sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==}
engines: {node: '>=4'}
+ normalize-wheel-es@1.2.0:
+ resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
+
npm-bundled@4.0.0:
resolution: {integrity: sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==}
engines: {node: ^18.17.0 || >=20.5.0}
@@ -8106,6 +8270,9 @@ packages:
zod:
optional: true
+ openapi-types@12.1.3:
+ resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
+
optipng-bin@7.0.1:
resolution: {integrity: sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA==}
engines: {node: '>=10'}
@@ -9218,11 +9385,6 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- typescript@5.8.3:
- resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
- engines: {node: '>=14.17'}
- hasBin: true
-
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -9329,7 +9491,7 @@ packages:
uuid@3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
- deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
+ deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
validate-npm-package-license@3.0.4:
@@ -9603,20 +9765,15 @@ packages:
vscode-uri@3.1.0:
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+ vue-component-type-helpers@3.3.1:
+ resolution: {integrity: sha512-pu58kqxmVyEH6VfNYW1UyEfR3XAnJ27ZXT3yzXxxpjLxVzAbyC35Zk/nm/RMs7ijWnJNSd9fWkeex2OhUsx3MA==}
+
vue-tsc@3.2.1:
resolution: {integrity: sha512-I23Rk8dkQfmcSbxDO0dmg9ioMLjKA1pjlU3Lz6Jfk2pMGu3Uryu9810XkcZH24IzPbhzPCnkKo2rEMRX0skSrw==}
hasBin: true
peerDependencies:
typescript: '>=5.0.0'
- vue@3.4.38:
- resolution: {integrity: sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==}
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
vue@3.5.26:
resolution: {integrity: sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==}
peerDependencies:
@@ -9813,6 +9970,19 @@ packages:
snapshots:
+ '@a2a-js/sdk@0.3.13(express@5.2.1)':
+ dependencies:
+ uuid: 11.1.0
+ optionalDependencies:
+ express: 5.2.1
+
+ '@a2a-js/sdk@1.0.0-beta.0(express@5.2.1)':
+ dependencies:
+ jose: 6.2.3
+ uuid: 11.1.0
+ optionalDependencies:
+ express: 5.2.1
+
'@ai-sdk/anthropic@2.0.57(zod@3.25.76)':
dependencies:
'@ai-sdk/provider': 2.0.1
@@ -10355,6 +10525,25 @@ snapshots:
rxjs: 7.8.2
tslib: 2.8.1
+ '@apidevtools/json-schema-ref-parser@14.0.1':
+ dependencies:
+ '@types/json-schema': 7.0.15
+ js-yaml: 4.3.0
+
+ '@apidevtools/openapi-schemas@2.1.0': {}
+
+ '@apidevtools/swagger-methods@3.0.2': {}
+
+ '@apidevtools/swagger-parser@12.1.0(openapi-types@12.1.3)':
+ dependencies:
+ '@apidevtools/json-schema-ref-parser': 14.0.1
+ '@apidevtools/openapi-schemas': 2.1.0
+ '@apidevtools/swagger-methods': 3.0.2
+ ajv: 8.17.1
+ ajv-draft-04: 1.0.0(ajv@8.17.1)
+ call-me-maybe: 1.0.2
+ openapi-types: 12.1.3
+
'@babel/code-frame@7.27.1':
dependencies:
'@babel/helper-validator-identifier': 7.28.5
@@ -10601,6 +10790,8 @@ snapshots:
'@colors/colors@1.5.0': {}
+ '@ctrl/tinycolor@4.2.0': {}
+
'@cush/relative@1.0.0': {}
'@dmsnell/diff-match-patch@1.1.0': {}
@@ -10629,6 +10820,10 @@ snapshots:
transitivePeerDependencies:
- '@algolia/client-search'
+ '@element-plus/icons-vue@2.3.2(vue@3.5.26(typescript@5.9.3))':
+ dependencies:
+ vue: 3.5.26(typescript@5.9.3)
+
'@esbuild/aix-ppc64@0.21.5':
optional: true
@@ -11467,7 +11662,7 @@ snapshots:
'@opentiny/genui-sdk-vue@1.1.0(typescript@5.9.3)(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))':
dependencies:
- '@opentiny/tiny-engine-builtin-component': 2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.29.0)(@opentiny/vue@3.28.0)(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
+ '@opentiny/tiny-engine-builtin-component': 2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd))(@opentiny/vue@3.28.0)(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))
'@opentiny/tiny-robot': 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/tiny-robot-kit': 0.3.3(vue@3.5.26(typescript@5.9.3))
'@opentiny/tiny-robot-svgs': 0.3.3(vue@3.5.26(typescript@5.9.3))
@@ -11480,7 +11675,7 @@ snapshots:
'@opentiny/vue-chart-radar': 3.14.0
'@opentiny/vue-chart-ring': 3.14.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.29.0
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-tabs': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -11491,6 +11686,8 @@ snapshots:
- typescript
- vite
+ '@opentiny/huicharts@1.0.1': {}
+
'@opentiny/ng-accordion@1.0.3(e235849e1e82bfc7f15a2631cb953652)':
dependencies:
'@angular/animations': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))
@@ -11615,7 +11812,7 @@ snapshots:
'@opentiny/ng-utils': 1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3)
tslib: 2.8.1
- '@opentiny/ng-checkbox@1.0.3(patch_hash=8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6)(7174416eb3899d125d62e3bb37f575f7)':
+ '@opentiny/ng-checkbox@1.0.3(7174416eb3899d125d62e3bb37f575f7)':
dependencies:
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
@@ -12222,13 +12419,13 @@ snapshots:
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
tslib: 2.8.1
- '@opentiny/ng-radio@1.0.3(344c6a87771dc9902a55b25db4decfe4)':
+ '@opentiny/ng-radio@1.0.3(efa8179383784b299e455f5810488503)':
dependencies:
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
'@angular/forms': 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
'@opentiny/ng-base': 1.0.3(abdfdc73c9ff34aa682e2833ed180114)
- '@opentiny/ng-checkbox': 1.0.3(patch_hash=8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6)(7174416eb3899d125d62e3bb37f575f7)
+ '@opentiny/ng-checkbox': 1.0.3(7174416eb3899d125d62e3bb37f575f7)
'@opentiny/ng-outline': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))
tslib: 2.8.1
@@ -12499,13 +12696,13 @@ snapshots:
'@opentiny/ng-utils': 1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3)
tslib: 2.8.1
- '@opentiny/ng-transfer@1.0.3(d21c6cc3860926a779823542a30b439b)':
+ '@opentiny/ng-transfer@1.0.3(e9efe23daf57bd2fd5be7a91c528e903)':
dependencies:
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
'@angular/forms': 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
'@opentiny/ng-base': 1.0.3(abdfdc73c9ff34aa682e2833ed180114)
- '@opentiny/ng-checkbox': 1.0.3(patch_hash=8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6)(7174416eb3899d125d62e3bb37f575f7)
+ '@opentiny/ng-checkbox': 1.0.3(7174416eb3899d125d62e3bb37f575f7)
'@opentiny/ng-drop': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-base@1.0.3(abdfdc73c9ff34aa682e2833ed180114))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
'@opentiny/ng-dropsearch': 1.0.3(ddd975c1fe0318a38d63adaf7a0e5da4)
'@opentiny/ng-icon': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-base@1.0.3(abdfdc73c9ff34aa682e2833ed180114))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
@@ -12518,14 +12715,14 @@ snapshots:
'@opentiny/ng-utils': 1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3)
tslib: 2.8.1
- '@opentiny/ng-tree@1.0.3(9aa3e5d8fe7643bcba55c01fb0b6f68b)':
+ '@opentiny/ng-tree@1.0.3(fe9b5bf0340d174fc177c4220e43f417)':
dependencies:
'@angular/cdk': 20.2.14(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
'@angular/forms': 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
'@opentiny/ng-base': 1.0.3(abdfdc73c9ff34aa682e2833ed180114)
- '@opentiny/ng-checkbox': 1.0.3(patch_hash=8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6)(7174416eb3899d125d62e3bb37f575f7)
+ '@opentiny/ng-checkbox': 1.0.3(7174416eb3899d125d62e3bb37f575f7)
'@opentiny/ng-icon': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-base@1.0.3(abdfdc73c9ff34aa682e2833ed180114))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
'@opentiny/ng-loading': 1.0.3(23152bcb17d21af9b3ec174ea1cd3127)
'@opentiny/ng-locale': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
@@ -12535,20 +12732,20 @@ snapshots:
'@opentiny/ng-validation': 1.0.3(849566d09b9cc3ffa0b8652ec1dfab54)
tslib: 2.8.1
- '@opentiny/ng-treeselect@1.0.3(509f9369209f38af9ffdb661e0f6f47d)':
+ '@opentiny/ng-treeselect@1.0.3(106c00ace8ede4cc99f9cb2be052a357)':
dependencies:
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
'@angular/forms': 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
'@opentiny/ng-base': 1.0.3(abdfdc73c9ff34aa682e2833ed180114)
- '@opentiny/ng-checkbox': 1.0.3(patch_hash=8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6)(7174416eb3899d125d62e3bb37f575f7)
+ '@opentiny/ng-checkbox': 1.0.3(7174416eb3899d125d62e3bb37f575f7)
'@opentiny/ng-dominator': 1.0.3(f3dd8ceb1fb67fd9d444e20b856eecbe)
'@opentiny/ng-drop': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-base@1.0.3(abdfdc73c9ff34aa682e2833ed180114))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
'@opentiny/ng-dropsearch': 1.0.3(ddd975c1fe0318a38d63adaf7a0e5da4)
'@opentiny/ng-locale': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
'@opentiny/ng-searchbox': 1.0.3(dfcab7284558d0798dd8667069c9ea43)
'@opentiny/ng-select': 1.0.3(40a5fb1e8336a2de12ad164fee9e28c6)
- '@opentiny/ng-tree': 1.0.3(9aa3e5d8fe7643bcba55c01fb0b6f68b)
+ '@opentiny/ng-tree': 1.0.3(fe9b5bf0340d174fc177c4220e43f417)
'@opentiny/ng-utils': 1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3)
tslib: 2.8.1
@@ -12600,7 +12797,7 @@ snapshots:
'@opentiny/ng-renderer': 1.0.3(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))
tslib: 2.8.1
- '@opentiny/ng@1.0.3(d1fd79d4fe287fdf8b571535719c5978)':
+ '@opentiny/ng@1.0.3(455eb20ddee0d8f7a1b17d72e1dc5cca)':
dependencies:
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
@@ -12617,7 +12814,7 @@ snapshots:
'@opentiny/ng-buttonselect': 1.0.3(0e54c758cc673ae00ea1dfe472bef208)
'@opentiny/ng-card': 1.0.3(33aee75538a801e6de9b6916fcc6bdfe)
'@opentiny/ng-cascader': 1.0.3(e86c25b99d97af72624dc6df195e8fa3)
- '@opentiny/ng-checkbox': 1.0.3(patch_hash=8ffd8f1d4e0e19e5b125c1f64ffca6e013de2c99df423497dffca0bf99bd13e6)(7174416eb3899d125d62e3bb37f575f7)
+ '@opentiny/ng-checkbox': 1.0.3(7174416eb3899d125d62e3bb37f575f7)
'@opentiny/ng-collapse': 1.0.3(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-utils@1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3))
'@opentiny/ng-collapsebox': 1.0.3(0f800a62ee393d5aef23ffe5641b4ab9)
'@opentiny/ng-collapsebutton': 1.0.3(6383ec1d195b1511f830e4f2e40cb1cc)
@@ -12674,7 +12871,7 @@ snapshots:
'@opentiny/ng-productpreview': 1.0.3(f3b0253d170f066bd47b5e6d635797fb)
'@opentiny/ng-progressbar': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-base@1.0.3(abdfdc73c9ff34aa682e2833ed180114))
'@opentiny/ng-progresspie': 1.0.3(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))
- '@opentiny/ng-radio': 1.0.3(344c6a87771dc9902a55b25db4decfe4)
+ '@opentiny/ng-radio': 1.0.3(efa8179383784b299e455f5810488503)
'@opentiny/ng-rate': 1.0.3(33aee75538a801e6de9b6916fcc6bdfe)
'@opentiny/ng-renderer': 1.0.3(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))
'@opentiny/ng-rights': 1.0.3(f4faf8f19b2e22f557f0e37bf4b9d42b)
@@ -12700,82 +12897,60 @@ snapshots:
'@opentiny/ng-time': 1.0.3(2e774488fa30dcf389fe28facf870fb3)
'@opentiny/ng-timeline': 1.0.3(f4faf8f19b2e22f557f0e37bf4b9d42b)
'@opentiny/ng-tip': 1.0.3(f32a4533fa3b81eee81fee76a4da057c)
- '@opentiny/ng-transfer': 1.0.3(d21c6cc3860926a779823542a30b439b)
- '@opentiny/ng-tree': 1.0.3(9aa3e5d8fe7643bcba55c01fb0b6f68b)
- '@opentiny/ng-treeselect': 1.0.3(509f9369209f38af9ffdb661e0f6f47d)
+ '@opentiny/ng-transfer': 1.0.3(e9efe23daf57bd2fd5be7a91c528e903)
+ '@opentiny/ng-tree': 1.0.3(fe9b5bf0340d174fc177c4220e43f417)
+ '@opentiny/ng-treeselect': 1.0.3(106c00ace8ede4cc99f9cb2be052a357)
'@opentiny/ng-upload': 1.0.3(c64cfb047be1b9b0f32c4b871bb6584e)
'@opentiny/ng-utils': 1.0.3(@angular/platform-browser-dynamic@21.0.6(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@20.3.15)(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))))(color@4.2.3)
'@opentiny/ng-validation': 1.0.3(849566d09b9cc3ffa0b8652ec1dfab54)
'@opentiny/ng-zoom': 1.0.3(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@opentiny/ng-renderer@1.0.3(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))
tslib: 2.8.1
- '@opentiny/tiny-engine-builtin-component@2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2)(@opentiny/vue@3.28.0)(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))(vue@3.5.26(typescript@5.9.3))':
+ '@opentiny/tiny-engine-builtin-component@2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd))(@opentiny/vue@3.28.0)(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@opentiny/vue': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
axios: 0.28.1
- vite-plugin-css-injected-by-js: 3.5.2(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))
+ vite-plugin-css-injected-by-js: 3.5.2(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
vue: 3.5.26(typescript@5.9.3)
transitivePeerDependencies:
- debug
- vite
- '@opentiny/tiny-engine-builtin-component@2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2)(@opentiny/vue@3.28.0)(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))':
+ '@opentiny/tiny-engine-builtin-component@2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd))(@opentiny/vue@3.28.0)(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@opentiny/vue': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
axios: 0.28.1
- vite-plugin-css-injected-by-js: 3.5.2(vite@6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
+ vite-plugin-css-injected-by-js: 3.5.2(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
vue: 3.5.26(typescript@5.9.3)
transitivePeerDependencies:
- debug
- vite
- '@opentiny/tiny-engine-builtin-component@2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.29.0)(@opentiny/vue@3.28.0)(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))':
+ '@opentiny/tiny-engine-builtin-component@2.9.0(@opentiny/vue-icon@3.28.3)(@opentiny/vue-renderless@3.30.0)(@opentiny/vue@3.28.0)(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@opentiny/vue': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.29.0
+ '@opentiny/vue-renderless': 3.30.0
axios: 0.28.1
- vite-plugin-css-injected-by-js: 3.5.2(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))
+ vite-plugin-css-injected-by-js: 3.5.2(vite@5.4.21(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1))
vue: 3.5.26(typescript@5.9.3)
transitivePeerDependencies:
- debug
- vite
- '@opentiny/tiny-robot-kit@0.3.3(vue@3.5.26(typescript@5.8.3))':
- dependencies:
- idb: 8.0.3
- vue: 3.5.26(typescript@5.8.3)
-
'@opentiny/tiny-robot-kit@0.3.3(vue@3.5.26(typescript@5.9.3))':
dependencies:
idb: 8.0.3
vue: 3.5.26(typescript@5.9.3)
- '@opentiny/tiny-robot-svgs@0.3.3(vue@3.4.38(typescript@5.9.3))':
- dependencies:
- vue: 3.4.38(typescript@5.9.3)
-
- '@opentiny/tiny-robot-svgs@0.3.3(vue@3.5.26(typescript@5.8.3))':
- dependencies:
- vue: 3.5.26(typescript@5.8.3)
-
'@opentiny/tiny-robot-svgs@0.3.3(vue@3.5.26(typescript@5.9.3))':
dependencies:
vue: 3.5.26(typescript@5.9.3)
- '@opentiny/tiny-robot@0.3.3(vue@3.5.26(typescript@5.8.3))':
- dependencies:
- '@opentiny/tiny-robot-svgs': 0.3.3(vue@3.5.26(typescript@5.8.3))
- '@opentiny/vue': 3.28.0
- '@vueuse/core': 13.9.0(vue@3.5.26(typescript@5.8.3))
- dompurify: 3.3.1
- markdown-it: 14.1.0
- vue: 3.5.26(typescript@5.8.3)
-
'@opentiny/tiny-robot@0.3.3(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@opentiny/tiny-robot-svgs': 0.3.3(vue@3.5.26(typescript@5.9.3))
@@ -12789,7 +12964,7 @@ snapshots:
dependencies:
xss: 1.0.14
- '@opentiny/utils@3.29.0':
+ '@opentiny/utils@3.30.0':
dependencies:
xss: 1.0.14
@@ -12800,7 +12975,7 @@ snapshots:
'@opentiny/vue-dropdown-item': 3.28.0
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-action-sheet@3.28.0':
@@ -12810,13 +12985,13 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-drawer': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-alert@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-amount@3.28.0':
@@ -12833,21 +13008,21 @@ snapshots:
'@opentiny/vue-popover': 3.28.0
'@opentiny/vue-radio': 3.28.0
'@opentiny/vue-radio-group': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-anchor@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-area@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -12856,7 +13031,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-flowchart': 3.28.0
'@opentiny/vue-loading': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-autocomplete@3.28.0':
dependencies:
@@ -12864,14 +13039,14 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-badge@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-base-select@3.28.0':
@@ -12886,7 +13061,7 @@ snapshots:
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-option': 3.28.0
'@opentiny/vue-recycle-scroller': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-select-dropdown': 3.28.0
'@opentiny/vue-tag': 3.28.0
@@ -12897,21 +13072,21 @@ snapshots:
'@opentiny/vue-breadcrumb-item@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-breadcrumb@3.28.0':
dependencies:
'@opentiny/vue-breadcrumb-item': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-bulletin-board@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tab-item': 3.28.0
'@opentiny/vue-tabs': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -12923,14 +13098,14 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-button@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-calendar-bar@3.28.0':
@@ -12938,7 +13113,7 @@ snapshots:
'@opentiny/vue-cascader-select': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-calendar-view@3.28.0':
dependencies:
@@ -12948,7 +13123,7 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-radio-button': 3.28.0
'@opentiny/vue-radio-group': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-slider-button': 3.28.0
'@opentiny/vue-slider-button-group': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -12960,21 +13135,21 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-card-group@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-card-template@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-card@3.28.0':
@@ -12986,20 +13161,20 @@ snapshots:
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-radio': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-carousel-item@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-carousel@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-cascader-menu@3.28.0':
@@ -13007,7 +13182,7 @@ snapshots:
'@opentiny/vue-cascader-node': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13019,7 +13194,7 @@ snapshots:
'@opentiny/vue-exception': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-cascader-node@3.28.0':
dependencies:
@@ -13029,14 +13204,14 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-radio': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-cascader-panel@3.28.0':
dependencies:
'@opentiny/vue-cascader-menu': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-cascader-select@3.28.0':
@@ -13044,7 +13219,7 @@ snapshots:
'@opentiny/vue-action-sheet': 3.28.0
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-cascader-view@3.28.0':
dependencies:
@@ -13054,7 +13229,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-exception': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-cascader@3.28.0':
dependencies:
@@ -13066,7 +13241,7 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-tag': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13077,7 +13252,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-chart-bar@3.14.0':
dependencies:
@@ -13125,7 +13300,7 @@ snapshots:
'@opentiny/vue-checkbox-button@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-checkbox-group@3.28.0':
@@ -13133,7 +13308,7 @@ snapshots:
'@opentiny/vue-checkbox': 3.28.0
'@opentiny/vue-checkbox-button': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-checkbox@3.28.0':
@@ -13141,13 +13316,13 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-col@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-collapse-item@3.28.0':
@@ -13155,7 +13330,7 @@ snapshots:
'@opentiny/vue-collapse-transition': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-collapse-transition@3.28.0':
@@ -13167,7 +13342,7 @@ snapshots:
'@opentiny/vue-collapse@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-color-picker@3.28.0':
@@ -13175,7 +13350,7 @@ snapshots:
'@opentiny/vue-color-select-panel': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-color-select-panel@3.28.0':
@@ -13188,14 +13363,14 @@ snapshots:
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-numeric': 3.28.0
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-column-list-group@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-column-list-item@3.28.0':
dependencies:
@@ -13206,7 +13381,7 @@ snapshots:
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-radio': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-common@3.14.0':
dependencies:
@@ -13221,7 +13396,7 @@ snapshots:
'@opentiny/utils': 3.28.0
'@opentiny/vue-hooks': 3.28.0
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
tailwind-merge: 1.14.0
@@ -13229,7 +13404,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13242,14 +13417,14 @@ snapshots:
'@opentiny/vue-container@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-country@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13257,7 +13432,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
cropperjs: 1.6.2
@@ -13266,7 +13441,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-select-mobile': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13282,7 +13457,7 @@ snapshots:
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-month-table': 3.28.0
'@opentiny/vue-popup': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-time': 3.28.0
'@opentiny/vue-year-table': 3.28.0
@@ -13294,7 +13469,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-recycle-scroller': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-time-picker-mobile': 3.28.0
'@opentiny/vue-date-picker@3.28.0':
@@ -13303,7 +13478,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-picker': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-date-range@3.28.0':
@@ -13314,7 +13489,7 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-time': 3.28.0
@@ -13322,7 +13497,7 @@ snapshots:
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-dept@3.28.0':
@@ -13333,7 +13508,7 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-row': 3.28.0
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13343,7 +13518,7 @@ snapshots:
'@opentiny/vue-action-sheet': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-dialog-select@3.28.0':
@@ -13351,11 +13526,11 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-dialog-box': 3.28.0
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-pager': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-selected-box': 3.28.0
'@opentiny/vue-split': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13370,7 +13545,7 @@ snapshots:
'@opentiny/vue-divider@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-drawer@3.28.0':
@@ -13378,7 +13553,7 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13387,7 +13562,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13395,7 +13570,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13404,14 +13579,14 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-dropdown-menu@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-dropdown-item': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13423,25 +13598,25 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-dynamic-scroller-item@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-dynamic-scroller@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-recycle-scroller': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-espace@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-exception@3.28.0':
@@ -13449,14 +13624,14 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-fall-menu@3.28.0':
dependencies:
'@opentiny/vue-col': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-row': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13470,7 +13645,7 @@ snapshots:
'@opentiny/vue-modal': 3.28.0
'@opentiny/vue-popover': 3.28.0
'@opentiny/vue-progress': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-switch': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13482,13 +13657,13 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-filter-box@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13497,7 +13672,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-filter-box': 3.28.0
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-filter@3.28.0':
@@ -13506,27 +13681,27 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-filter-bar': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-float-button@3.28.0':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-floatbar@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-floating-button@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-flowchart@3.28.0':
dependencies:
@@ -13535,7 +13710,7 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-fluent-editor@3.28.0':
@@ -13544,20 +13719,20 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-image-viewer': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
- '@opentiny/vue-form-item@3.28.0':
+ '@opentiny/vue-form-item@3.28.0(patch_hash=0efe71be369a844388c7f28464c4b352cb43480c7fea7c457a96eb555ba5bd95)':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-form@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13565,23 +13740,23 @@ snapshots:
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-grid-column@3.28.0':
dependencies:
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-grid-manager@3.28.0':
dependencies:
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-grid-select@3.28.0':
dependencies:
'@opentiny/vue-base-select': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-grid': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-grid-toolbar@3.28.0':
dependencies:
@@ -13597,7 +13772,7 @@ snapshots:
'@opentiny/vue-dropdown': 3.28.0
'@opentiny/vue-dropdown-item': 3.28.0
'@opentiny/vue-dropdown-menu': 3.28.0
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-layout': 3.28.0
@@ -13607,7 +13782,7 @@ snapshots:
'@opentiny/vue-popover': 3.28.0
'@opentiny/vue-radio': 3.28.0
'@opentiny/vue-radio-group': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-row': 3.28.0
'@opentiny/vue-search': 3.28.0
'@opentiny/vue-select': 3.28.0
@@ -13618,7 +13793,7 @@ snapshots:
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-tree': 3.28.0
- '@opentiny/vue-grid@3.28.0':
+ '@opentiny/vue-grid@3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
@@ -13632,7 +13807,7 @@ snapshots:
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-modal': 3.28.0
'@opentiny/vue-pager': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tag': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13642,7 +13817,7 @@ snapshots:
'@floating-ui/dom': 1.7.4
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
shepherd.js: 11.1.1
@@ -13651,10 +13826,10 @@ snapshots:
'@floating-ui/dom': 1.7.4
'@opentiny/utils': 3.28.0
- '@opentiny/vue-hooks@3.29.0':
+ '@opentiny/vue-hooks@3.30.0':
dependencies:
'@floating-ui/dom': 1.7.4
- '@opentiny/utils': 3.29.0
+ '@opentiny/utils': 3.30.0
'@opentiny/vue-hrapprover@3.28.0':
dependencies:
@@ -13664,8 +13839,174 @@ snapshots:
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-modal': 3.28.0
'@opentiny/vue-radio': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
+ '@opentiny/vue-theme': 3.28.0
+
+ '@opentiny/vue-huicharts-amap@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-bar@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-bmap@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-boxplot@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-candle@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ '@opentiny/vue-locale': 3.28.0
+
+ '@opentiny/vue-huicharts-core@3.28.0':
+ dependencies:
+ '@opentiny/huicharts': 1.0.1
+ '@opentiny/utils': 3.28.0
+ '@opentiny/vue-theme': 3.28.0
+ echarts: 5.4.1
+
+ '@opentiny/vue-huicharts-funnel@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-gauge@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-graph@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-heatmap@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-histogram@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-line@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-liquidfill@3.28.0(echarts@5.4.1)':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ echarts-liquidfill: 3.1.0(echarts@5.4.1)
+ transitivePeerDependencies:
+ - echarts
+
+ '@opentiny/vue-huicharts-map@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-pie@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ '@opentiny/vue-locale': 3.28.0
+
+ '@opentiny/vue-huicharts-process@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-radar@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-ring@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ '@opentiny/vue-locale': 3.28.0
+
+ '@opentiny/vue-huicharts-sankey@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-scatter@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-sunburst@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-tree@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+
+ '@opentiny/vue-huicharts-waterfall@3.28.0':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ '@opentiny/vue-locale': 3.28.0
+
+ '@opentiny/vue-huicharts-wordcloud@3.28.0(echarts@5.4.1)':
+ dependencies:
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ echarts-wordcloud: 2.0.0(echarts@5.4.1)
+ transitivePeerDependencies:
+ - echarts
+
+ '@opentiny/vue-huicharts@3.28.0(echarts@5.4.1)':
+ dependencies:
+ '@opentiny/huicharts': 1.0.1
+ '@opentiny/utils': 3.28.0
+ '@opentiny/vue-common': 3.28.0
+ '@opentiny/vue-huicharts-amap': 3.28.0
+ '@opentiny/vue-huicharts-bar': 3.28.0
+ '@opentiny/vue-huicharts-bmap': 3.28.0
+ '@opentiny/vue-huicharts-boxplot': 3.28.0
+ '@opentiny/vue-huicharts-candle': 3.28.0
+ '@opentiny/vue-huicharts-core': 3.28.0
+ '@opentiny/vue-huicharts-funnel': 3.28.0
+ '@opentiny/vue-huicharts-gauge': 3.28.0
+ '@opentiny/vue-huicharts-graph': 3.28.0
+ '@opentiny/vue-huicharts-heatmap': 3.28.0
+ '@opentiny/vue-huicharts-histogram': 3.28.0
+ '@opentiny/vue-huicharts-line': 3.28.0
+ '@opentiny/vue-huicharts-liquidfill': 3.28.0(echarts@5.4.1)
+ '@opentiny/vue-huicharts-map': 3.28.0
+ '@opentiny/vue-huicharts-pie': 3.28.0
+ '@opentiny/vue-huicharts-process': 3.28.0
+ '@opentiny/vue-huicharts-radar': 3.28.0
+ '@opentiny/vue-huicharts-ring': 3.28.0
+ '@opentiny/vue-huicharts-sankey': 3.28.0
+ '@opentiny/vue-huicharts-scatter': 3.28.0
+ '@opentiny/vue-huicharts-sunburst': 3.28.0
+ '@opentiny/vue-huicharts-tree': 3.28.0
+ '@opentiny/vue-huicharts-waterfall': 3.28.0
+ '@opentiny/vue-huicharts-wordcloud': 3.28.0(echarts@5.4.1)
+ '@opentiny/vue-locale': 3.28.0
'@opentiny/vue-theme': 3.28.0
+ transitivePeerDependencies:
+ - echarts
'@opentiny/vue-icon@3.28.3':
dependencies:
@@ -13681,7 +14022,7 @@ snapshots:
'@opentiny/vue-dropdown-item': 3.28.0
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-image@3.28.0':
@@ -13690,7 +14031,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-image-viewer': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-input@3.28.0':
@@ -13700,7 +14041,7 @@ snapshots:
'@opentiny/vue-dialog-box': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13708,13 +14049,13 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-layout@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-link-menu@3.28.0':
@@ -13724,28 +14065,28 @@ snapshots:
'@opentiny/vue-dialog-box': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tree': 3.28.0
'@opentiny/vue-link@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-load-list@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-loading@3.28.0':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-locale@3.14.0':
@@ -13757,7 +14098,7 @@ snapshots:
'@opentiny/vue-locale@3.28.0':
dependencies:
'@opentiny/utils': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-locales@3.28.0':
@@ -13766,18 +14107,18 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-logon-user@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-logout@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-menu@3.28.0':
@@ -13787,7 +14128,7 @@ snapshots:
'@opentiny/vue-exception': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-message@3.28.0':
dependencies:
@@ -13799,14 +14140,14 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-mind-map@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
mind-elixir: 3.3.2
@@ -13818,7 +14159,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popconfirm': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-month-range@3.28.0':
@@ -13827,21 +14168,21 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-month-table': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-month-table@3.28.0':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-nav-menu@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -13849,7 +14190,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-number-animation@3.28.0':
@@ -13857,7 +14198,7 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-modal': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-statistic': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -13869,14 +14210,14 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-radio': 3.28.0
'@opentiny/vue-radio-group': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tag': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-option-group@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-option@3.28.0':
@@ -13884,14 +14225,14 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-pager-item@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-pager@3.28.0':
dependencies:
@@ -13902,14 +14243,14 @@ snapshots:
'@opentiny/vue-loading': 3.28.0
'@opentiny/vue-pager-item': 3.28.0
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-panel@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-picker@3.28.0':
dependencies:
@@ -13923,7 +14264,7 @@ snapshots:
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-month-range': 3.28.0
'@opentiny/vue-quarter-panel': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-time': 3.28.0
'@opentiny/vue-time-panel': 3.28.0
@@ -13941,7 +14282,7 @@ snapshots:
'@opentiny/vue-modal': 3.28.0
'@opentiny/vue-popconfirm': 3.28.0
'@opentiny/vue-progress': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-popconfirm@3.28.0':
@@ -13950,7 +14291,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-popeditor@3.28.0':
@@ -13958,11 +14299,11 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-dialog-box': 3.28.0
'@opentiny/vue-directive': 3.28.0
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-pager': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-selected-box': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tree': 3.28.0
@@ -13971,21 +14312,21 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-popup@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-progress@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-pull-refresh@3.28.0':
@@ -13993,12 +14334,12 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-loading': 3.28.0
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-qr-code@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
qrcode: 1.5.1
@@ -14006,7 +14347,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-year-table': 3.28.0
@@ -14023,7 +14364,7 @@ snapshots:
'@opentiny/vue-option': 3.28.0
'@opentiny/vue-option-group': 3.28.0
'@opentiny/vue-radio': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-time-picker': 3.28.0
@@ -14032,7 +14373,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -14041,14 +14382,14 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-radio': 3.28.0
'@opentiny/vue-radio-button': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-radio@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-rate@3.28.0':
@@ -14056,7 +14397,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-record@3.28.0':
@@ -14064,14 +14405,14 @@ snapshots:
'@opentiny/vue-action-sheet': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-recycle-scroller@3.28.0':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-renderless@3.14.1':
@@ -14079,22 +14420,22 @@ snapshots:
color: 4.2.3
xss: 1.0.11
- '@opentiny/vue-renderless@3.28.2':
+ '@opentiny/vue-renderless@3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-hooks': 3.28.0
color: 4.2.3
- '@opentiny/vue-renderless@3.29.0':
+ '@opentiny/vue-renderless@3.30.0':
dependencies:
- '@opentiny/utils': 3.29.0
- '@opentiny/vue-hooks': 3.29.0
+ '@opentiny/utils': 3.30.0
+ '@opentiny/vue-hooks': 3.30.0
color: 4.2.3
'@opentiny/vue-river@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
echarts: 5.4.1
'@opentiny/vue-roles@3.28.0':
@@ -14102,26 +14443,26 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-row@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-scroll-text@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-scrollbar@3.28.0':
dependencies:
'@opentiny/utils': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-search@3.28.0':
@@ -14131,7 +14472,7 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-select-dropdown@3.28.0':
@@ -14139,7 +14480,7 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-search': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -14152,7 +14493,7 @@ snapshots:
'@opentiny/vue-exception': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select-view@3.28.0':
dependencies:
@@ -14162,7 +14503,7 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-exception': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select-wrapper@3.28.0':
dependencies:
@@ -14170,13 +14511,13 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-filter-box': 3.28.0
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-option': 3.28.0
'@opentiny/vue-recycle-scroller': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-select-dropdown': 3.28.0
'@opentiny/vue-tag': 3.28.0
@@ -14190,13 +14531,13 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-filter-box': 3.28.0
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-option': 3.28.0
'@opentiny/vue-recycle-scroller': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-select-dropdown': 3.28.0
'@opentiny/vue-tag': 3.28.0
@@ -14209,7 +14550,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-signature@3.28.0':
@@ -14219,19 +14560,19 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-locale': 3.28.0
'@opentiny/vue-modal': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-skeleton-item@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-skeleton@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-skeleton-item': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -14239,33 +14580,33 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-slider-button': 3.28.0
'@opentiny/vue-slider-button@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-slider@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-space@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-split@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-standard-list-item@3.28.0':
@@ -14275,7 +14616,7 @@ snapshots:
'@opentiny/vue-dropdown-item': 3.28.0
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tag-group': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-user-head': 3.28.0
@@ -14283,7 +14624,7 @@ snapshots:
'@opentiny/vue-statistic@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-steps@3.28.0':
@@ -14292,44 +14633,44 @@ snapshots:
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-sticky@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-switch@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tab-item@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tabbar-item@3.28.0':
dependencies:
'@opentiny/vue-badge': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tabbar@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tabbar-item': 3.28.0
'@opentiny/vue-table@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tabs@3.28.0':
@@ -14342,7 +14683,7 @@ snapshots:
'@opentiny/vue-dropdown-menu': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-locale': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tooltip': 3.28.0
@@ -14351,7 +14692,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tag': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -14359,13 +14700,13 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-text-popup@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-theme-mobile@3.14.2': {}
@@ -14378,14 +14719,14 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-timeline-item': 3.28.0
'@opentiny/vue-time-panel@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -14393,7 +14734,7 @@ snapshots:
dependencies:
'@opentiny/vue-cascader-select': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-time-picker@3.28.0':
dependencies:
@@ -14406,7 +14747,7 @@ snapshots:
dependencies:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-time-spinner': 3.28.0
@@ -14422,7 +14763,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-scrollbar': 3.28.0
'@opentiny/vue-theme': 3.28.0
@@ -14430,7 +14771,7 @@ snapshots:
dependencies:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-time-spinner': 3.28.0
@@ -14438,7 +14779,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-toggle-menu@3.28.0':
@@ -14446,14 +14787,14 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tree': 3.28.0
'@opentiny/vue-tooltip@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-top-box@3.28.0':
@@ -14461,7 +14802,7 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-transfer-panel@3.28.0':
@@ -14471,14 +14812,14 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-pager': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-transfer@3.28.0':
dependencies:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-transfer-panel': 3.28.0
@@ -14487,7 +14828,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-input': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-tree': 3.28.0
@@ -14495,7 +14836,7 @@ snapshots:
dependencies:
'@opentiny/vue-base-select': 3.28.0
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tree': 3.28.0
'@opentiny/vue-tree@3.28.0':
@@ -14509,14 +14850,14 @@ snapshots:
'@opentiny/vue-input': 3.28.0
'@opentiny/vue-popover': 3.28.0
'@opentiny/vue-radio': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-switch': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-upload-dragger@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-upload-list@3.28.0':
dependencies:
@@ -14527,7 +14868,7 @@ snapshots:
'@opentiny/vue-modal': 3.28.0
'@opentiny/vue-progress': 3.28.0
'@opentiny/vue-record': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-upload@3.28.0':
@@ -14536,7 +14877,7 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-modal': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tooltip': 3.28.0
'@opentiny/vue-upload-dragger': 3.28.0
@@ -14544,7 +14885,7 @@ snapshots:
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-logout': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-user-contact': 3.28.0
@@ -14555,21 +14896,21 @@ snapshots:
'@opentiny/vue-espace': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-user-head': 3.28.0
'@opentiny/vue-user-head-group@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-user-head': 3.28.0
'@opentiny/vue-user-head@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-user-link@3.28.0':
@@ -14578,7 +14919,7 @@ snapshots:
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-loading': 3.28.0
'@opentiny/vue-popover': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-user@3.28.0':
@@ -14586,19 +14927,19 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
'@opentiny/vue-option': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-select': 3.28.0
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-virtual-scroll-box@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-virtual-tree@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-tree': 3.28.0
'@opentiny/vue-virtual-scroll-box': 3.28.0
@@ -14610,7 +14951,7 @@ snapshots:
'@opentiny/vue-watermark@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-wizard@3.28.0':
@@ -14618,7 +14959,7 @@ snapshots:
'@opentiny/vue-button': 3.28.0
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue-user-contact': 3.28.0
@@ -14627,13 +14968,13 @@ snapshots:
'@opentiny/vue-common': 3.28.0
'@opentiny/vue-directive': 3.28.0
'@opentiny/vue-icon': 3.28.3
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-year-table': 3.28.0
'@opentiny/vue-year-table@3.28.0':
dependencies:
'@opentiny/vue-common': 3.28.0
- '@opentiny/vue-renderless': 3.28.2
+ '@opentiny/vue-renderless': 3.28.2(patch_hash=eb3ac6e181df6a7b1b1d12df90f8c6775eeab5e34da8d6c96016768645b502fd)
'@opentiny/vue-theme': 3.28.0
'@opentiny/vue@3.28.0':
@@ -14717,9 +15058,9 @@ snapshots:
'@opentiny/vue-flowchart': 3.28.0
'@opentiny/vue-fluent-editor': 3.28.0
'@opentiny/vue-form': 3.28.0
- '@opentiny/vue-form-item': 3.28.0
+ '@opentiny/vue-form-item': 3.28.0(patch_hash=0efe71be369a844388c7f28464c4b352cb43480c7fea7c457a96eb555ba5bd95)
'@opentiny/vue-fullscreen': 3.28.0
- '@opentiny/vue-grid': 3.28.0
+ '@opentiny/vue-grid': 3.28.0(patch_hash=5804a772cfa5dbdd98b44ad85c2fd415f883f253e07b73445ab36217cd250bd0)
'@opentiny/vue-grid-column': 3.28.0
'@opentiny/vue-grid-manager': 3.28.0
'@opentiny/vue-grid-select': 3.28.0
@@ -15258,6 +15599,8 @@ snapshots:
'@standard-schema/spec@1.1.0': {}
+ '@sxzz/popperjs-es@2.11.8': {}
+
'@trysound/sax@0.2.0': {}
'@tufjs/canonical-json@2.0.0': {}
@@ -15362,6 +15705,10 @@ snapshots:
'@types/jasmine@5.1.13': {}
+ '@types/js-yaml@4.0.9': {}
+
+ '@types/json-schema@7.0.15': {}
+
'@types/json5@0.0.29': {}
'@types/keyv@3.1.4':
@@ -15370,8 +15717,14 @@ snapshots:
'@types/linkify-it@5.0.0': {}
+ '@types/lodash-es@4.17.12':
+ dependencies:
+ '@types/lodash': 4.17.24
+
'@types/lodash@4.17.21': {}
+ '@types/lodash@4.17.24': {}
+
'@types/markdown-it@14.1.2':
dependencies:
'@types/linkify-it': 5.0.0
@@ -15466,17 +15819,17 @@ snapshots:
vite: 6.4.1(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
vue: 3.5.26(typescript@5.9.3)
- '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.4.38(typescript@5.9.3))':
+ '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.53
vite: 7.3.0(@types/node@17.0.45)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
- vue: 3.4.38(typescript@5.9.3)
+ vue: 3.5.26(typescript@5.9.3)
- '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.8.3))':
+ '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.53
vite: 7.3.0(@types/node@25.5.0)(less@4.5.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)
- vue: 3.5.26(typescript@5.8.3)
+ vue: 3.5.26(typescript@5.9.3)
'@vitest/expect@3.2.4':
dependencies:
@@ -15597,14 +15950,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@vue/compiler-core@3.4.38':
- dependencies:
- '@babel/parser': 7.28.5
- '@vue/shared': 3.4.38
- entities: 4.5.0
- estree-walker: 2.0.2
- source-map-js: 1.2.1
-
'@vue/compiler-core@3.5.26':
dependencies:
'@babel/parser': 7.28.5
@@ -15613,28 +15958,11 @@ snapshots:
estree-walker: 2.0.2
source-map-js: 1.2.1
- '@vue/compiler-dom@3.4.38':
- dependencies:
- '@vue/compiler-core': 3.4.38
- '@vue/shared': 3.4.38
-
'@vue/compiler-dom@3.5.26':
dependencies:
'@vue/compiler-core': 3.5.26
'@vue/shared': 3.5.26
- '@vue/compiler-sfc@3.4.38':
- dependencies:
- '@babel/parser': 7.28.5
- '@vue/compiler-core': 3.4.38
- '@vue/compiler-dom': 3.4.38
- '@vue/compiler-ssr': 3.4.38
- '@vue/shared': 3.4.38
- estree-walker: 2.0.2
- magic-string: 0.30.21
- postcss: 8.5.6
- source-map-js: 1.2.1
-
'@vue/compiler-sfc@3.5.26':
dependencies:
'@babel/parser': 7.28.5
@@ -15647,11 +15975,6 @@ snapshots:
postcss: 8.5.6
source-map-js: 1.2.1
- '@vue/compiler-ssr@3.4.38':
- dependencies:
- '@vue/compiler-dom': 3.4.38
- '@vue/shared': 3.4.38
-
'@vue/compiler-ssr@3.5.26':
dependencies:
'@vue/compiler-dom': 3.5.26
@@ -15703,31 +16026,15 @@ snapshots:
path-browserify: 1.0.1
picomatch: 4.0.3
- '@vue/reactivity@3.4.38':
- dependencies:
- '@vue/shared': 3.4.38
-
'@vue/reactivity@3.5.26':
dependencies:
'@vue/shared': 3.5.26
- '@vue/runtime-core@3.4.38':
- dependencies:
- '@vue/reactivity': 3.4.38
- '@vue/shared': 3.4.38
-
'@vue/runtime-core@3.5.26':
dependencies:
'@vue/reactivity': 3.5.26
'@vue/shared': 3.5.26
- '@vue/runtime-dom@3.4.38':
- dependencies:
- '@vue/reactivity': 3.4.38
- '@vue/runtime-core': 3.4.38
- '@vue/shared': 3.4.38
- csstype: 3.2.3
-
'@vue/runtime-dom@3.5.26':
dependencies:
'@vue/reactivity': 3.5.26
@@ -15735,37 +16042,18 @@ snapshots:
'@vue/shared': 3.5.26
csstype: 3.2.3
- '@vue/server-renderer@3.4.38(vue@3.4.38(typescript@5.9.3))':
- dependencies:
- '@vue/compiler-ssr': 3.4.38
- '@vue/shared': 3.4.38
- vue: 3.4.38(typescript@5.9.3)
-
- '@vue/server-renderer@3.5.26(vue@3.5.26(typescript@5.8.3))':
- dependencies:
- '@vue/compiler-ssr': 3.5.26
- '@vue/shared': 3.5.26
- vue: 3.5.26(typescript@5.8.3)
-
'@vue/server-renderer@3.5.26(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@vue/compiler-ssr': 3.5.26
'@vue/shared': 3.5.26
vue: 3.5.26(typescript@5.9.3)
- '@vue/shared@3.4.38': {}
-
'@vue/shared@3.5.26': {}
- '@vue/tsconfig@0.7.0(typescript@5.8.3)(vue@3.5.26(typescript@5.8.3))':
- optionalDependencies:
- typescript: 5.8.3
- vue: 3.5.26(typescript@5.8.3)
-
- '@vue/tsconfig@0.8.1(typescript@5.9.3)(vue@3.4.38(typescript@5.9.3))':
+ '@vue/tsconfig@0.7.0(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))':
optionalDependencies:
typescript: 5.9.3
- vue: 3.4.38(typescript@5.9.3)
+ vue: 3.5.26(typescript@5.9.3)
'@vue/tsconfig@0.8.1(typescript@5.9.3)(vue@3.5.26(typescript@5.9.3))':
optionalDependencies:
@@ -15781,26 +16069,27 @@ snapshots:
transitivePeerDependencies:
- typescript
- '@vueuse/core@13.9.0(vue@3.5.26(typescript@5.8.3))':
+ '@vueuse/core@13.9.0(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@types/web-bluetooth': 0.0.21
'@vueuse/metadata': 13.9.0
- '@vueuse/shared': 13.9.0(vue@3.5.26(typescript@5.8.3))
- vue: 3.5.26(typescript@5.8.3)
+ '@vueuse/shared': 13.9.0(vue@3.5.26(typescript@5.9.3))
+ vue: 3.5.26(typescript@5.9.3)
- '@vueuse/core@13.9.0(vue@3.5.26(typescript@5.9.3))':
+ '@vueuse/core@14.3.0(vue@3.5.26(typescript@5.9.3))':
dependencies:
'@types/web-bluetooth': 0.0.21
- '@vueuse/metadata': 13.9.0
- '@vueuse/shared': 13.9.0(vue@3.5.26(typescript@5.9.3))
+ '@vueuse/metadata': 14.3.0
+ '@vueuse/shared': 14.3.0(vue@3.5.26(typescript@5.9.3))
vue: 3.5.26(typescript@5.9.3)
- '@vueuse/integrations@12.8.2(focus-trap@7.7.1)(qrcode@1.5.1)(typescript@5.9.3)':
+ '@vueuse/integrations@12.8.2(async-validator@4.2.5)(focus-trap@7.7.1)(qrcode@1.5.1)(typescript@5.9.3)':
dependencies:
'@vueuse/core': 12.8.2(typescript@5.9.3)
'@vueuse/shared': 12.8.2(typescript@5.9.3)
vue: 3.5.26(typescript@5.9.3)
optionalDependencies:
+ async-validator: 4.2.5
focus-trap: 7.7.1
qrcode: 1.5.1
transitivePeerDependencies:
@@ -15810,17 +16099,19 @@ snapshots:
'@vueuse/metadata@13.9.0': {}
+ '@vueuse/metadata@14.3.0': {}
+
'@vueuse/shared@12.8.2(typescript@5.9.3)':
dependencies:
vue: 3.5.26(typescript@5.9.3)
transitivePeerDependencies:
- typescript
- '@vueuse/shared@13.9.0(vue@3.5.26(typescript@5.8.3))':
+ '@vueuse/shared@13.9.0(vue@3.5.26(typescript@5.9.3))':
dependencies:
- vue: 3.5.26(typescript@5.8.3)
+ vue: 3.5.26(typescript@5.9.3)
- '@vueuse/shared@13.9.0(vue@3.5.26(typescript@5.9.3))':
+ '@vueuse/shared@14.3.0(vue@3.5.26(typescript@5.9.3))':
dependencies:
vue: 3.5.26(typescript@5.9.3)
@@ -15842,6 +16133,9 @@ snapshots:
acorn@8.15.0: {}
+ acorn@8.17.0:
+ optional: true
+
adler-32@1.3.1: {}
agent-base@7.1.4: {}
@@ -15890,6 +16184,10 @@ snapshots:
optionalDependencies:
ajv: 8.13.0
+ ajv-draft-04@1.0.0(ajv@8.17.1):
+ optionalDependencies:
+ ajv: 8.17.1
+
ajv-formats@3.0.1(ajv@8.13.0):
optionalDependencies:
ajv: 8.13.0
@@ -15999,6 +16297,8 @@ snapshots:
assertion-error@2.0.1: {}
+ async-validator@4.2.5: {}
+
asynckit@0.4.0: {}
available-typed-arrays@1.0.7:
@@ -16250,6 +16550,8 @@ snapshots:
call-bind-apply-helpers: 1.0.2
get-intrinsic: 1.3.0
+ call-me-maybe@1.0.2: {}
+
camel-case@4.1.2:
dependencies:
pascal-case: 3.1.2
@@ -16622,6 +16924,8 @@ snapshots:
date-format@4.0.14: {}
+ dayjs@1.11.20: {}
+
de-indent@1.0.2: {}
debug@2.6.9:
@@ -16836,6 +17140,14 @@ snapshots:
eastasianwidth@0.2.0: {}
+ echarts-liquidfill@3.1.0(echarts@5.4.1):
+ dependencies:
+ echarts: 5.4.1
+
+ echarts-wordcloud@2.0.0(echarts@5.4.1):
+ dependencies:
+ echarts: 5.4.1
+
echarts@5.4.1:
dependencies:
tslib: 2.3.0
@@ -16845,6 +17157,25 @@ snapshots:
electron-to-chromium@1.5.267: {}
+ element-plus@2.14.0(vue@3.5.26(typescript@5.9.3)):
+ dependencies:
+ '@ctrl/tinycolor': 4.2.0
+ '@element-plus/icons-vue': 2.3.2(vue@3.5.26(typescript@5.9.3))
+ '@floating-ui/dom': 1.7.4
+ '@popperjs/core': '@sxzz/popperjs-es@2.11.8'
+ '@types/lodash': 4.17.24
+ '@types/lodash-es': 4.17.12
+ '@vueuse/core': 14.3.0(vue@3.5.26(typescript@5.9.3))
+ async-validator: 4.2.5
+ dayjs: 1.11.20
+ lodash: 4.18.1
+ lodash-es: 4.18.1
+ lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1)
+ memoize-one: 6.0.0
+ normalize-wheel-es: 1.2.0
+ vue: 3.5.26(typescript@5.9.3)
+ vue-component-type-helpers: 3.3.1
+
elliptic@6.6.1:
dependencies:
bn.js: 4.12.2
@@ -17298,8 +17629,6 @@ snapshots:
extend@3.0.2: {}
- extensionless@1.9.9: {}
-
fast-deep-equal@3.1.3: {}
fast-diff@1.3.0: {}
@@ -18064,6 +18393,8 @@ snapshots:
jose@6.1.3: {}
+ jose@6.2.3: {}
+
jpegtran-bin@5.0.2:
dependencies:
bin-build: 3.0.0
@@ -18079,6 +18410,10 @@ snapshots:
js-tokens@9.0.1: {}
+ js-yaml@4.3.0:
+ dependencies:
+ argparse: 2.0.1
+
jsesc@3.1.0: {}
json-buffer@3.0.0: {}
@@ -18255,12 +18590,22 @@ snapshots:
lodash-es@4.17.22: {}
+ lodash-es@4.18.1: {}
+
+ lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1):
+ dependencies:
+ '@types/lodash-es': 4.17.12
+ lodash: 4.18.1
+ lodash-es: 4.18.1
+
lodash.clonedeep@4.5.0: {}
lodash.isequal@4.5.0: {}
lodash@4.17.21: {}
+ lodash@4.18.1: {}
+
log-symbols@6.0.0:
dependencies:
chalk: 5.6.2
@@ -18415,6 +18760,8 @@ snapshots:
media-typer@1.1.0: {}
+ memoize-one@6.0.0: {}
+
meow@3.7.0:
dependencies:
camelcase-keys: 2.1.0
@@ -18566,10 +18913,10 @@ snapshots:
pkg-types: 1.3.1
ufo: 1.6.1
- monaco-editor-vue3@1.0.5(monaco-editor@0.55.1)(vue@3.5.26(typescript@5.8.3)):
+ monaco-editor-vue3@1.0.5(monaco-editor@0.55.1)(vue@3.5.26(typescript@5.9.3)):
dependencies:
monaco-editor: 0.55.1
- vue: 3.5.26(typescript@5.8.3)
+ vue: 3.5.26(typescript@5.9.3)
monaco-editor@0.55.1:
dependencies:
@@ -18739,6 +19086,8 @@ snapshots:
query-string: 5.1.1
sort-keys: 2.0.0
+ normalize-wheel-es@1.2.0: {}
+
npm-bundled@4.0.0:
dependencies:
npm-normalize-package-bin: 4.0.0
@@ -18867,6 +19216,8 @@ snapshots:
ws: 8.18.3
zod: 4.1.13
+ openapi-types@12.1.3: {}
+
optipng-bin@7.0.1:
dependencies:
bin-build: 3.0.0
@@ -19963,7 +20314,7 @@ snapshots:
terser@5.44.1:
dependencies:
'@jridgewell/source-map': 0.3.11
- acorn: 8.15.0
+ acorn: 8.17.0
commander: 2.20.3
source-map-support: 0.5.21
optional: true
@@ -20085,8 +20436,6 @@ snapshots:
typescript@5.8.2: {}
- typescript@5.8.3: {}
-
typescript@5.9.3: {}
ua-parser-js@0.7.41: {}
@@ -20564,18 +20913,18 @@ snapshots:
terser: 5.44.1
tsx: 4.21.0
- vitepress-demo-plugin@1.5.1(shiki@2.5.0)(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3)):
+ vitepress-demo-plugin@1.5.1(shiki@2.5.0)(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3)):
dependencies:
shiki: 2.5.0
- vitepress: 1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3)
+ vitepress: 1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3)
vue: 3.5.26(typescript@5.9.3)
- vitepress-plugin-tabs@0.7.3(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3)):
+ vitepress-plugin-tabs@0.7.3(vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3))(vue@3.5.26(typescript@5.9.3)):
dependencies:
- vitepress: 1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3)
+ vitepress: 1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3)
vue: 3.5.26(typescript@5.9.3)
- vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3):
+ vitepress@1.6.4(@algolia/client-search@5.35.0)(@types/node@25.5.0)(async-validator@4.2.5)(less@4.5.1)(postcss@8.5.6)(qrcode@1.5.1)(sass@1.97.1)(search-insights@2.17.3)(terser@5.44.1)(typescript@5.9.3):
dependencies:
'@docsearch/css': 3.8.2
'@docsearch/js': 3.8.2(@algolia/client-search@5.35.0)(search-insights@2.17.3)
@@ -20588,7 +20937,7 @@ snapshots:
'@vue/devtools-api': 7.7.9
'@vue/shared': 3.5.26
'@vueuse/core': 12.8.2(typescript@5.9.3)
- '@vueuse/integrations': 12.8.2(focus-trap@7.7.1)(qrcode@1.5.1)(typescript@5.9.3)
+ '@vueuse/integrations': 12.8.2(async-validator@4.2.5)(focus-trap@7.7.1)(qrcode@1.5.1)(typescript@5.9.3)
focus-trap: 7.7.1
mark.js: 8.11.1
minisearch: 7.2.0
@@ -20713,11 +21062,7 @@ snapshots:
vscode-uri@3.1.0: {}
- vue-tsc@3.2.1(typescript@5.8.3):
- dependencies:
- '@volar/typescript': 2.4.27
- '@vue/language-core': 3.2.1
- typescript: 5.8.3
+ vue-component-type-helpers@3.3.1: {}
vue-tsc@3.2.1(typescript@5.9.3):
dependencies:
@@ -20725,26 +21070,6 @@ snapshots:
'@vue/language-core': 3.2.1
typescript: 5.9.3
- vue@3.4.38(typescript@5.9.3):
- dependencies:
- '@vue/compiler-dom': 3.4.38
- '@vue/compiler-sfc': 3.4.38
- '@vue/runtime-dom': 3.4.38
- '@vue/server-renderer': 3.4.38(vue@3.4.38(typescript@5.9.3))
- '@vue/shared': 3.4.38
- optionalDependencies:
- typescript: 5.9.3
-
- vue@3.5.26(typescript@5.8.3):
- dependencies:
- '@vue/compiler-dom': 3.5.26
- '@vue/compiler-sfc': 3.5.26
- '@vue/runtime-dom': 3.5.26
- '@vue/server-renderer': 3.5.26(vue@3.5.26(typescript@5.8.3))
- '@vue/shared': 3.5.26
- optionalDependencies:
- typescript: 5.8.3
-
vue@3.5.26(typescript@5.9.3):
dependencies:
'@vue/compiler-dom': 3.5.26
diff --git a/projects/tiny-schema-renderer b/projects/tiny-schema-renderer
index a972bed5..52ce2c46 160000
--- a/projects/tiny-schema-renderer
+++ b/projects/tiny-schema-renderer
@@ -1 +1 @@
-Subproject commit a972bed5730ad559e49cd55b4da0b04058241a16
+Subproject commit 52ce2c466d8be21baa156243de8c421382d21f03
diff --git a/projects/tiny-schema-renderer-ng/angular.json b/projects/tiny-schema-renderer-ng/angular.json
index 4b2d4a10..eea21015 100644
--- a/projects/tiny-schema-renderer-ng/angular.json
+++ b/projects/tiny-schema-renderer-ng/angular.json
@@ -181,7 +181,10 @@
"test": {
"builder": "@angular/build:karma",
"options": {
- "tsConfig": "projects/renderer/tsconfig.spec.json"
+ "tsConfig": "projects/renderer/tsconfig.spec.json",
+ "include": [
+ "../__test__/**/*.spec.ts"
+ ]
}
}
}
diff --git a/projects/tiny-schema-renderer-ng/package.json b/projects/tiny-schema-renderer-ng/package.json
index 55ff47c0..4cfc487a 100644
--- a/projects/tiny-schema-renderer-ng/package.json
+++ b/projects/tiny-schema-renderer-ng/package.json
@@ -38,8 +38,6 @@
"@angular/material": "^20.2.14",
"@angular/platform-browser": "^20.3.0",
"@angular/router": "^20.3.0",
- "@opentiny/ng": "^1.0.3",
- "@opentiny/ng-themes": "^1.0.3",
"lodash": "4.17.21",
"postcss": "8.5.6",
"postcss-selector-parser": "7.1.0",
@@ -51,6 +49,8 @@
"@angular/build": "^20.3.10",
"@angular/cli": "^20.3.10",
"@angular/compiler-cli": "^20.3.0",
+ "@opentiny/ng": "^1.0.3",
+ "@opentiny/ng-themes": "^1.0.3",
"@types/jasmine": "~5.1.0",
"@types/lodash": "^4.17.21",
"jasmine-core": "~5.9.0",
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/__test__/apply-default-props.spec.ts b/projects/tiny-schema-renderer-ng/projects/renderer/__test__/apply-default-props.spec.ts
new file mode 100644
index 00000000..ef32d02d
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/__test__/apply-default-props.spec.ts
@@ -0,0 +1,160 @@
+import { applyDefaultPropsToProps, type PropsValue } from '../src/apply-default-props';
+import type { DefaultPropsMap } from '../src/renderer-materials';
+
+const COMPONENT = 'Select';
+
+const defaultPropsMap: DefaultPropsMap = {
+ [COMPONENT]: {
+ placeholder: '请选择',
+ type: 'primary',
+ clearable: true,
+ 'style.color': '#333',
+ 'options.*.label': '默认标签',
+ meta: { },
+ 'meta.nested': {},
+ 'meta.nested.count': 1,
+ },
+};
+
+const schemaProps: Record = {
+ size: 'small',
+ type: 'danger',
+ style: {},
+ options: [
+ { value: 'a' },
+ { value: 'b', label: '已有标签' },
+ null,
+ 'invalid-item',
+ ],
+};
+
+function cloneSchemaProps(): Record {
+ return structuredClone(schemaProps);
+}
+
+function applyDefaults(props: Record): void {
+ applyDefaultPropsToProps(COMPONENT, props, defaultPropsMap);
+}
+
+describe('applyDefaultPropsToProps', () => {
+ it('补齐 schema 中缺失的叶子属性', () => {
+ const props = cloneSchemaProps();
+ applyDefaults(props);
+
+ expect(props['size']).toBe('small');
+ expect(props['placeholder']).toBe('请选择');
+ expect(props['clearable']).toBe(true);
+ });
+
+ it('不覆盖 schema 中已有的值', () => {
+ const props = cloneSchemaProps();
+ applyDefaults(props);
+
+ expect(props['type']).toBe('danger');
+ });
+
+ it('路径已存在时补齐嵌套叶子属性', () => {
+ const props = cloneSchemaProps();
+ applyDefaults(props);
+
+ expect(props['style']).toEqual({ color: '#333' });
+ });
+
+ it('中间路径不存在时跳过嵌套默认值', () => {
+ const props = cloneSchemaProps();
+ delete props['style'];
+ applyDefaults(props);
+
+ expect(props['style']).toBeUndefined();
+ });
+
+ it('通配路径为 options 每一项补齐 label', () => {
+ const props = cloneSchemaProps();
+ applyDefaults(props);
+
+ const options = props['options'] as PropsValue[];
+ expect(options[0]).toEqual({ value: 'a', label: '默认标签' });
+ expect(options[1]).toEqual({ value: 'b', label: '已有标签' });
+ expect(options[2]).toBeNull();
+ expect(options[3]).toBe('invalid-item');
+ });
+
+ it('中间路径不存在时跳过数组下标路径', () => {
+ const props: Record = {};
+ applyDefaultPropsToProps(COMPONENT, props, {
+ [COMPONENT]: { 'options.0.label': '首项默认' },
+ });
+
+ expect(props['options']).toBeUndefined();
+ });
+
+ it('通配路径在 options 不是数组时按对象键名读取', () => {
+ const props: Record = {
+ options: { '*': { value: 'a' } },
+ };
+ applyDefaultPropsToProps(COMPONENT, props, {
+ [COMPONENT]: { 'options.*.label': '默认标签' },
+ });
+
+ expect((props['options'] as Record)['*']).toEqual({
+ value: 'a',
+ label: '默认标签',
+ });
+ });
+
+ it('数字键在对象上按普通属性读取', () => {
+ const props: Record = {
+ items: { '0': { name: '已有' } },
+ };
+ applyDefaultPropsToProps(COMPONENT, props, {
+ [COMPONENT]: { 'items.0.name': '默认名称' },
+ });
+
+ expect((props['items'] as Record)['0']).toEqual({ name: '已有' });
+ });
+
+ it('options 不是数组时跳过无法下钻的路径', () => {
+ const props = cloneSchemaProps();
+ props['options'] = 'not-array';
+ applyDefaults(props);
+
+ expect(props['options']).toBe('not-array');
+ });
+
+ it('options 不存在时跳过通配路径', () => {
+ const props = cloneSchemaProps();
+ delete props['options'];
+ applyDefaults(props);
+
+ expect(props['options']).toBeUndefined();
+ });
+
+ it('默认值使用深拷贝,不污染 defaultPropsMap', () => {
+ const props: Record = {};
+ applyDefaults(props);
+
+ expect(props['meta']).toEqual({ nested: { count: 1 } });
+ (props['meta'] as Record)['nested'] = { count: 2 };
+ expect(defaultPropsMap[COMPONENT]!['meta']).toEqual({ nested: { count: 1 } });
+ });
+
+ it('defaultPropsMap 无效时不修改 props', () => {
+ const props = cloneSchemaProps();
+ const before = structuredClone(props);
+
+ applyDefaultPropsToProps(COMPONENT, props, null);
+ applyDefaultPropsToProps(COMPONENT, props, undefined);
+ applyDefaultPropsToProps(COMPONENT, props, {} as DefaultPropsMap);
+
+ expect(props).toEqual(before);
+ });
+
+ it('组件无配置时不修改 props', () => {
+ const props = cloneSchemaProps();
+ const before = structuredClone(props);
+
+ applyDefaultPropsToProps('OtherComponent', props, defaultPropsMap);
+
+ expect(props).toEqual(before);
+ });
+});
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/apply-default-props.pipe.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/apply-default-props.pipe.ts
new file mode 100644
index 00000000..55fd811f
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/apply-default-props.pipe.ts
@@ -0,0 +1,20 @@
+import { inject, Pipe, PipeTransform } from '@angular/core';
+import { RENDERER_SETTINGS } from './renderer-settings';
+import { applyDefaultPropsToProps } from './apply-default-props';
+
+@Pipe({
+ name: 'applyDefaultProps',
+ standalone: true,
+})
+export class ApplyDefaultPropsPipe implements PipeTransform {
+ private readonly rendererSettings = inject(RENDERER_SETTINGS, { optional: true });
+
+ transform(
+ props: Record | null | undefined,
+ componentName: string,
+ ): Record {
+ const result = { ...(props ?? {}) };
+ applyDefaultPropsToProps(componentName, result, this.rendererSettings?.materials?.defaultPropsMap);
+ return result;
+ }
+}
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/apply-default-props.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/apply-default-props.ts
new file mode 100644
index 00000000..7bd61fc9
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/apply-default-props.ts
@@ -0,0 +1,111 @@
+import type { DefaultPropsMap } from './renderer-materials';
+
+export type PropsValue = any;
+export type DefaultValue = any;
+
+type Container = Record | PropsValue[];
+
+function isContainer(value: PropsValue): value is Container {
+ return typeof value === 'object' && value !== null;
+}
+
+function cloneDefaultValue(value: PropsValue): PropsValue {
+ if (!isContainer(value)) {
+ return value;
+ }
+ return structuredClone(value);
+}
+
+function getChild(container: Container, key: string): PropsValue {
+ if (Array.isArray(container) && /^\d+$/.test(key)) {
+ return container[Number(key)];
+ }
+ return (container as Record)[key];
+}
+
+function setChild(container: Container, key: string, value: PropsValue): void {
+ if (Array.isArray(container) && /^\d+$/.test(key)) {
+ container[Number(key)] = value;
+ } else {
+ (container as Record)[key] = value;
+ }
+}
+
+function fillAtPath(
+ current: Container,
+ keys: string[],
+ defaultValue: DefaultValue,
+): void {
+ if (!keys.length) {
+ return;
+ }
+
+ const [key, ...rest] = keys;
+
+ if (key === '*' && Array.isArray(current)) {
+ for (let i = 0; i < current.length; i++) {
+ if (!rest.length) {
+ if (current[i] == null) {
+ current[i] = cloneDefaultValue(defaultValue);
+ }
+ continue;
+ }
+ const item = current[i];
+ if (item == null || !isContainer(item)) {
+ continue;
+ }
+ fillAtPath(item, rest, defaultValue);
+ }
+ return;
+ }
+
+ if (!rest.length) {
+ if (getChild(current, key) == null) {
+ setChild(current, key, cloneDefaultValue(defaultValue));
+ }
+ return;
+ }
+
+ const nextValue = getChild(current, key);
+ if (nextValue == null) {
+ return;
+ }
+
+ if (rest[0] === '*' && Array.isArray(nextValue)) {
+ fillAtPath(nextValue, rest, defaultValue);
+ return;
+ }
+
+ if (!isContainer(nextValue)) {
+ return;
+ }
+
+ fillAtPath(nextValue, rest, defaultValue);
+}
+
+function fillMissingValue(
+ target: Record,
+ propertyPath: string,
+ defaultValue: DefaultValue,
+): void {
+ fillAtPath(target, propertyPath.split('.'), defaultValue);
+}
+
+export function applyDefaultPropsToProps(
+ componentName: string,
+ props: Record,
+ defaultPropsMap: DefaultPropsMap | null | undefined,
+): void {
+ if (typeof componentName !== 'string' || !isContainer(defaultPropsMap)) {
+ return;
+ }
+
+ const componentDefaults = defaultPropsMap[componentName];
+ if (!componentDefaults) {
+ return;
+ }
+
+ Object.entries(componentDefaults).forEach(([propertyPath, defaultValue]) => {
+ fillMissingValue(props, propertyPath, defaultValue);
+ });
+}
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/auto-apply-directives.pipe.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/auto-apply-directives.pipe.ts
index ae4dbde9..a40f9cc2 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/auto-apply-directives.pipe.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/auto-apply-directives.pipe.ts
@@ -1,19 +1,26 @@
import { Pipe, PipeTransform } from '@angular/core';
-import { autoApplyDirectivePattern } from './parser/material-getter';
+import { RendererContextService } from './context.service';
+import { getAutoApplyPatterns, getDirective } from './parser/material-getter';
@Pipe({
name: 'autoApplyDirectives',
- standalone: true,
+ standalone: true
})
export class AutoApplyDirectivesPipe implements PipeTransform {
+ constructor(private readonly contextService: RendererContextService) {}
+
transform(directives: {directiveName: string}[] | undefined, schema: any) {
- const appendDirectives = Object.entries(autoApplyDirectivePattern).filter(([key, fn]) => fn(schema)).reduce((acc,cur)=> {
- if (!directives?.find(d => d.directiveName === cur[0])) {
- acc.push({directiveName: cur[0]});
+ const context = this.contextService.getContext();
+ const patterns = getAutoApplyPatterns(context);
+ const appendDirectives = Object.entries(patterns)
+ .filter(([key, fn]) => getDirective(key, context) && fn(schema, context)) // TODO 暂无法获取 context 中的 materials,缺少 Symbol
+ .reduce((acc, [key]) => {
+ if (!directives?.find(d => d.directiveName === key)) {
+ acc.push({directiveName: key});
}
return acc;
- }, [] as {directiveName: string}[]);
+ }, [] as {directiveName: string}[]);
const result = [...(directives || []), ...appendDirectives]
return result.length ? result : undefined;
}
-}
\ No newline at end of file
+}
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/context.service.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/context.service.ts
index 66d3207f..b3d983fa 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/context.service.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/context.service.ts
@@ -1,8 +1,10 @@
import { Injectable } from '@angular/core';
+import { MATERIALS_CONTEXT_KEY, type IRendererMaterials } from './renderer-materials';
@Injectable()
export class RendererContextService {
- private context: Record = {};
+ private context: Record = {};
+
constructor() {
this.context = {};
}
@@ -16,4 +18,7 @@ export class RendererContextService {
Object.assign(this.context, context);
}
+ setMaterials(materials: IRendererMaterials) {
+ this.context[MATERIALS_CONTEXT_KEY] = materials ?? {};
+ }
}
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/get-directive.pipe.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/get-directive.pipe.ts
index 705f4e11..e416f216 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/get-directive.pipe.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/get-directive.pipe.ts
@@ -1,4 +1,5 @@
import { Pipe, PipeTransform, Type } from '@angular/core';
+import { RendererContextService } from './context.service';
import { getDirective } from './parser/material-getter';
@Pipe({
@@ -6,11 +7,14 @@ import { getDirective } from './parser/material-getter';
standalone: true,
})
export class GetDirectivesPipe implements PipeTransform {
+ constructor(private readonly contextService: RendererContextService) {}
+
transform(directives: { directiveName: string }[] | undefined): Type[] | undefined {
if (!directives || !directives.length) return undefined;
+ const context = this.contextService.getContext();
return directives
.map(({ directiveName }) => {
- const directive = getDirective(directiveName);
+ const directive = getDirective(directiveName, context);
if (!directive || !('ɵdir' in directive)) return null;
return directive;
})
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/life-cycles.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/life-cycles.ts
new file mode 100644
index 00000000..4d3f8627
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/life-cycles.ts
@@ -0,0 +1,70 @@
+import { parseData } from './parser/schema-parser';
+
+export interface JSFunctionDescriptor {
+ type: 'JSFunction';
+ value: string;
+ params?: string[];
+}
+
+export interface LifeCycles {
+ onMounted?: JSFunctionDescriptor;
+ onUnmounted?: JSFunctionDescriptor;
+}
+
+/**
+ * 将 schema 中的 lifeCycles 字段规范化为生命周期对象。
+ *
+ * @param lifeCycles - schema 中的 lifeCycles 配置
+ * @returns 规范化后的生命周期对象,无效输入时返回空对象
+ */
+const normalizeLifeCycles = (lifeCycles: unknown): LifeCycles => {
+ if (lifeCycles == null || typeof lifeCycles !== 'object' || Array.isArray(lifeCycles)) {
+ return {};
+ }
+ return lifeCycles as LifeCycles;
+};
+
+/**
+ * 将生命周期配置解析为可执行的函数。
+ * 在回调执行时重新解析,确保使用最新的渲染上下文。
+ *
+ * @param source - 生命周期函数描述(通常为 JSFunction)
+ * @param getContext - 获取当前渲染上下文的函数
+ * @returns 解析成功时返回可执行函数,否则返回 null
+ */
+const parseLifeCycleFn = (
+ source: JSFunctionDescriptor | undefined,
+ getContext: () => Record,
+): (() => void | Promise) | null => {
+ if (source == null) {
+ return null;
+ }
+ return () => {
+ try {
+ const parsed = parseData(source, {}, getContext());
+ if (typeof parsed === 'function') {
+ return parsed();
+ }
+ } catch (error) {
+ console.error('LifeCycle parse error:', error);
+ }
+ };
+};
+
+/**
+ * 从 schema 的 lifeCycles 配置中解析页面级 onMounted / onUnmounted 回调。
+ *
+ * @param lifeCycles - schema 中的 lifeCycles 配置
+ * @param getContext - 获取当前渲染上下文的函数
+ * @returns 包含 onMounted 与 onUnmounted 回调的对象
+ */
+export const getPageLifeCycleFns = (
+ lifeCycles: LifeCycles | null | undefined,
+ getContext: () => Record,
+) => {
+ const cycles = normalizeLifeCycles(lifeCycles);
+ return {
+ onMounted: parseLifeCycleFn(cycles.onMounted, getContext),
+ onUnmounted: parseLifeCycleFn(cycles.onUnmounted, getContext),
+ };
+};
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/material-getter.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/material-getter.ts
index 599e4310..b877da75 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/material-getter.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/material-getter.ts
@@ -1,141 +1,63 @@
import { type Type } from '@angular/core';
+import {
+ MATERIALS_CONTEXT_KEY,
+ type AutoApplyDirectivePattern,
+ type IRendererMaterials,
+} from '../renderer-materials';
import { isHTMLTag } from './parser-utils';
import { RendererTextComponent } from '../buildin/renderer-text.component';
-import { RendererImageComponent } from '../buildin/renderer-image.component';
-import {
- TiButtonComponent,
- TiButtonModule,
- TiSelectComponent,
- TiSelectModule,
- TiTextComponent,
- TiTextModule,
- TiTableComponent,
- TiTableModule,
- TiModalComponent,
- TiModalModule,
- TiDateComponent,
- TiDateModule,
- TiPaginationComponent,
- TiPaginationModule,
- TiTabsComponent,
- TiTabModule,
- TiCheckboxComponent,
- TiCheckboxModule,
- TiCheckboxGroupComponent,
- TiRadioComponent,
- TiRadioModule,
- TiRadioGroupComponent,
- TiTabComponent,
- TiSwitchComponent,
- TiSwitchModule,
- TiTipDirective,
- TiCardComponent,
- TiCardModule,
- TiUploadComponent,
- TiUploadModule,
- TiFormfieldComponent,
- TiFormfieldModule,
- TiCardHeaderComponent,
- TiItemComponent,
- TiDateRangeComponent,
- TiDateRangeModule,
- TiSliderComponent,
- TiSliderModule,
- TiRateComponent,
- TiRateModule,
- TiTextareaComponent,
- TiTextareaModule,
-} from '@opentiny/ng';
import { CheckboxControlValueAccessor, DefaultValueAccessor, NgModel } from '@angular/forms';
import { LogDirective } from '../buildin/log.directive';
import { nativeElementComponentFactory } from '../native-element.component';
export const Mapper: Record> = {
Text: RendererTextComponent,
- Img: RendererImageComponent,
- TiButton: TiButtonComponent,
- TiSelect: TiSelectComponent,
- TiText: TiTextComponent,
- TiTable: TiTableComponent,
- TiModal: TiModalComponent,
- TiDate: TiDateComponent,
- TiPagination: TiPaginationComponent,
- TiTabs: TiTabsComponent,
- TiTab: TiTabComponent,
- TiCheckbox: TiCheckboxComponent,
- TiCheckboxGroup: TiCheckboxGroupComponent,
- TiRadio: TiRadioComponent,
- TiRadioGroup: TiRadioGroupComponent,
- TiSwitch: TiSwitchComponent,
- TiCard: TiCardComponent,
- TiUpload: TiUploadComponent,
- TiFormField: TiFormfieldComponent,
- TiCardHeader: TiCardHeaderComponent,
- TiItem: TiItemComponent,
- TiDateRange: TiDateRangeComponent,
- TiSlider: TiSliderComponent,
- TiRate: TiRateComponent,
- TiTextArea: TiTextareaComponent,
};
-export const ModuleRef: Record> = {
- TiButton: TiButtonModule,
- TiSelect: TiSelectModule,
- TiText: TiTextModule,
- TiTable: TiTableModule,
- TiModal: TiModalModule,
- TiDate: TiDateModule,
- TiPagination: TiPaginationModule,
- TiTabs: TiTabModule,
- TiCheckbox: TiCheckboxModule,
- TiCheckboxGroup: TiCheckboxModule,
- TiRadio: TiRadioModule,
- TiRadioGroup: TiRadioModule,
- TiSwitch: TiSwitchModule,
- TiCard: TiCardModule,
- TiUpload: TiUploadModule,
- TiFormField: TiFormfieldModule,
- TiCardHeader: TiCardModule,
- TiItem: TiFormfieldModule,
- TiDateRange: TiDateRangeModule,
- TiSlider: TiSliderModule,
- TiRate: TiRateModule,
- TiTextArea: TiTextareaModule,
-};
+export const ModuleRef: Record> = {};
export const directiveMap: Record> = {
ngModel: NgModel,
defaultValueAccessor: DefaultValueAccessor,
checkboxValueAccessor: CheckboxControlValueAccessor,
log: LogDirective,
- TiTip: TiTipDirective,
};
-// 指令需要标记为standalone
+
(NgModel['ɵdir'] as any).standalone = true;
(DefaultValueAccessor['ɵdir'] as any).standalone = true;
(CheckboxControlValueAccessor['ɵdir'] as any).standalone = true;
-// 部分组件需要修改默认搭配的selector
-(TiTextComponent['ɵcmp'] as any).selectors[0][0] = 'input';
-(TiTextareaComponent['ɵcmp'] as any).selectors[0][0] = 'textarea';
-(TiRadioComponent['ɵcmp'] as any).selectors[0][0] = 'input';
-(TiCheckboxComponent['ɵcmp'] as any).selectors[0][0] = 'input';
export const iconMap: Record = {};
export const customElements: Record> = {};
-export const getComponent = (name: string): Type | null => {
+export const getMaterials = (context: Record = {}): IRendererMaterials =>
+ context[MATERIALS_CONTEXT_KEY] ?? {};
+
+export const getComponent = (
+ name: string,
+ context: Record = {},
+): Type | null => {
return (
Mapper[name] ||
+ getMaterials(context).components?.[name] ||
customElements[name] ||
- (isHTMLTag(name, true) ? createComponent(name as string) : null)
+ (isHTMLTag(name, true) ? createComponent(name) : null)
);
};
-export const getModuleRef = (name: string): Type | undefined => {
- return ModuleRef[name] || undefined;
+
+export const getModuleRef = (
+ name: string,
+ context: Record = {},
+): Type | undefined => {
+ return ModuleRef[name] || getMaterials(context).modules?.[name];
};
-export const getDirective = (name: string): Type | undefined => {
- return directiveMap[name] || undefined;
+
+export const getDirective = (
+ name: string,
+ context: Record = {},
+): Type | undefined => {
+ return directiveMap[name] || getMaterials(context).directives?.[name];
};
export const createComponent = (component: string): Type => {
@@ -144,26 +66,31 @@ export const createComponent = (component: string): Type => {
return componentFactory;
};
-export const autoApplyDirectivePattern: Record boolean> = {
- ngModel: (schema: any) => !!(schema?.props?.ngModel || schema?.props?.onNgModelChange),
- defaultValueAccessor: (schema: any) => {
- const componentType = getComponent(schema?.componentName);
- if (!(componentType as any)?.['ɵcmp']) {
- return false;
- }
- const componentSelectors = (componentType as any)?.['ɵcmp']?.selectors;
- const selectorMatch = () => ['input', 'textarea'].includes(componentSelectors[0][0]);
- const propsMatch = () => schema?.props?.['ngModel'] && schema?.props?.type !== 'checkbox';
- return selectorMatch() && propsMatch();
- },
- checkboxValueAccessor: (schema: any) => {
- const componentType = getComponent(schema?.componentName);
- if (!(componentType as any)?.['ɵcmp']) {
- return false;
- }
- const componentSelectors = (componentType as any)?.['ɵcmp']?.selectors;
- const selectorMatch = () => ['input'].includes(componentSelectors[0][0]);
- const propsMatch = () => schema?.props?.['ngModel'] && schema?.props?.type === 'checkbox';
- return selectorMatch() && propsMatch();
- },
+export const getAutoApplyPatterns = (
+ context: Record = {},
+): AutoApplyDirectivePattern => {
+ return {
+ ngModel: (schema: any) => !!(schema?.props?.ngModel || schema?.props?.onNgModelChange),
+ defaultValueAccessor: (schema: any, ctx = {}) => {
+ const componentType = getComponent(schema?.componentName, ctx);
+ if (!(componentType as any)?.['ɵcmp']) {
+ return false;
+ }
+ const componentSelectors = (componentType as any)?.['ɵcmp']?.selectors;
+ const selectorMatch = () => ['input', 'textarea'].includes(componentSelectors?.[0]?.[0] ?? '');
+ const propsMatch = () => schema?.props?.['ngModel'] && schema?.props?.type !== 'checkbox';
+ return selectorMatch() && propsMatch();
+ },
+ checkboxValueAccessor: (schema: any, ctx = {}) => {
+ const componentType = getComponent(schema?.componentName, ctx);
+ if (!(componentType as any)?.['ɵcmp']) {
+ return false;
+ }
+ const componentSelectors = (componentType as any)?.['ɵcmp']?.selectors;
+ const selectorMatch = () => ['input'].includes(componentSelectors?.[0]?.[0] ?? '');
+ const propsMatch = () => schema?.props?.['ngModel'] && schema?.props?.type === 'checkbox';
+ return selectorMatch() && propsMatch();
+ },
+ ...(getMaterials(context).autoApplyDirectives ?? {}),
+ };
};
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/schema-parser.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/schema-parser.ts
index 698f1a0b..9a2e2e09 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/schema-parser.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/parser/schema-parser.ts
@@ -108,7 +108,7 @@ const parseJSXFunction = (data: any, ctx: any) => {
return newFn(...fnInfo.params, fnInfo.body).bind({
...ctx,
- getComponent,
+ getComponent: (name: string) => getComponent(name, ctx),
});
} catch (error) {
Notify({
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/public-api.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/public-api.ts
index 59d79da5..0cb229ee 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/public-api.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/public-api.ts
@@ -3,4 +3,7 @@
*/
export * from './renderer-main';
+export * from './renderer-materials';
export * from './parser/material-getter';
+export { RENDERER_SETTINGS } from './renderer-settings';
+export type { IRendererSettings } from './renderer-settings';
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-main.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-main.ts
index 91a84184..d094eace 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-main.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-main.ts
@@ -1,7 +1,17 @@
-import { Component, ElementRef, Input, NgZone, SimpleChanges } from '@angular/core';
-// import { Renderer } from './renderer';
+import {
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ inject,
+ Input,
+ NgZone,
+ OnDestroy,
+ SimpleChanges,
+} from '@angular/core';
+import { RENDERER_SETTINGS } from './renderer-settings';
import { RendererContextService } from './context.service';
import { parseData } from './parser/schema-parser';
+import { getPageLifeCycleFns } from './life-cycles';
import { setPageCss } from './css/page-css';
import { CommonModule } from '@angular/common';
import { LoadingComponent } from './loading.component';
@@ -40,18 +50,23 @@ function reset(obj: any) {
`,
})
-export class RendererMain {
+export class RendererMain implements OnDestroy {
@Input() schema: any = {};
pageSchema: any = {};
methods: any = {};
state: any = {};
cssScopeId: string = '';
+ private pageOnUnmounted: (() => void | Promise) | null = null;
+ private readonly rendererSettings = inject(RENDERER_SETTINGS, { optional: true });
+
constructor(
private contextService: RendererContextService,
private el: ElementRef,
private ngZone: NgZone,
+ private cdr: ChangeDetectorRef,
) {
this.cssScopeId = `data-schema-${Math.random().toString(36).slice(2, 8)}`;
+ this.contextService.setMaterials(this.rendererSettings?.materials ?? {});
}
ngAfterViewInit() {
@@ -68,6 +83,23 @@ export class RendererMain {
}
}
+ ngOnDestroy() {
+ void this.invokePageOnUnmounted();
+ }
+
+ private async invokePageOnUnmounted() {
+ const fn = this.pageOnUnmounted;
+ this.pageOnUnmounted = null;
+ if (typeof fn !== 'function') {
+ return;
+ }
+ try {
+ await fn();
+ } catch (error) {
+ console.error('RendererMain onUnmounted error:', error);
+ }
+ }
+
get rootSchema() {
return {
componentName: 'div',
@@ -124,9 +156,27 @@ export class RendererMain {
this.contextService.setContext(context, true);
this.setMethods(newSchema.methods || {}, true);
this._setState(newSchema.state || {}, true);
+
+ await this.invokePageOnUnmounted();
+
+ const { onMounted: onMountedFn, onUnmounted: onUnmountedFn } = getPageLifeCycleFns(
+ newSchema.lifeCycles,
+ () => this.contextService.getContext(),
+ );
+
+ setPageCss(newSchema.css || '', this.cssScopeId);
+ delete newSchema.lifeCycles;
Object.assign(this.pageSchema, newSchema);
+
await new Promise((resolve) => setTimeout(resolve, 0));
- setPageCss(newSchema.css || '', this.cssScopeId);
+
+ try {
+ await onMountedFn?.();
+ this.pageOnUnmounted = onUnmountedFn;
+ this.ngZone.run(() => this.cdr.detectChanges());
+ } catch (error) {
+ console.error('RendererMain onMounted error:', error);
+ }
}
public detectChanges() {
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-materials.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-materials.ts
new file mode 100644
index 00000000..e2659ab8
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-materials.ts
@@ -0,0 +1,18 @@
+import { type Type } from '@angular/core';
+
+export type DefaultPropsMap = Record>;
+
+export type AutoApplyDirectivePattern = Record<
+ string,
+ (schema: any, ctx?: Record) => boolean
+>;
+
+export interface IRendererMaterials {
+ components?: Record>;
+ modules?: Record>;
+ directives?: Record>;
+ autoApplyDirectives?: AutoApplyDirectivePattern;
+ defaultPropsMap?: DefaultPropsMap;
+}
+
+export const MATERIALS_CONTEXT_KEY = Symbol('renderer-materials');
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-settings.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-settings.ts
new file mode 100644
index 00000000..09ab8f15
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-settings.ts
@@ -0,0 +1,8 @@
+import { InjectionToken } from '@angular/core';
+import type { IRendererMaterials } from './renderer-materials';
+
+export interface IRendererSettings {
+ materials?: IRendererMaterials;
+}
+
+export const RENDERER_SETTINGS = new InjectionToken('RENDERER_SETTINGS');
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.html b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.html
index 4719f2f6..4d9b918f 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.html
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.html
@@ -31,7 +31,7 @@
[componentOutlet]="schema.componentName | getComponent"
[componentOutletNgModule]="schema.componentName | getModuleRef"
[componentOutletInjector]="injector"
- [componentOutletProps]="context | parseData: schema.props : mergeScope"
+ [componentOutletProps]="context | parseData: schema.props : mergeScope | applyDefaultProps: schema.componentName"
[componentOutletDirectives]="schema.directives | autoApplyDirectives: schema | getDirectives "
[componentOutletContent]="
{
@@ -42,7 +42,7 @@
attrAndEvent
[attrs]="
[
- context | parseData: schema.props : mergeScope | propsFilter: 'attributes' : (schema.componentName | getComponent),
+ context | parseData: schema.props : mergeScope | applyDefaultProps: schema.componentName | propsFilter: 'attributes' : (schema.componentName | getComponent),
internalAttributes
] | mergeObject
"
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.ts b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.ts
index b3f57bd1..9073ac0f 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.ts
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer-template.component.ts
@@ -1,6 +1,7 @@
import { Component, Injector, Pipe, PipeTransform, TemplateRef, Type, ViewChild, ViewContainerRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RendererContextService } from './context.service';
+import { getComponent, getModuleRef } from './parser/material-getter';
import { EmbeddedViewPipe } from './embedded-view.pipe';
import { LoopScopePipe } from './loop-scope.pipe';
@@ -9,9 +10,9 @@ import { PropsFilterPipe } from './props-filter.pipe';
import { GetDirectivesPipe } from './get-directive.pipe';
import { ComponentOutlet } from './component-outlet';
import { ParseDataPipe } from './parse-data.pipe';
+import { ApplyDefaultPropsPipe } from './apply-default-props.pipe';
import { MergeObjectPipe } from './merge-object.pipe';
import { AutoApplyDirectivesPipe } from './auto-apply-directives.pipe';
-import { getComponent, getModuleRef } from './parser/material-getter';
import { RendererDirective } from './renderer.directive';
@Pipe({
@@ -19,8 +20,10 @@ import { RendererDirective } from './renderer.directive';
standalone: true,
})
export class GetModuleRefPipe implements PipeTransform {
+ constructor(private readonly contextService: RendererContextService) {}
+
transform(componentName: string): Type | undefined {
- return componentName ? getModuleRef(componentName) : undefined;
+ return componentName ? getModuleRef(componentName, this.contextService.getContext()) : undefined;
}
}
@@ -29,8 +32,10 @@ export class GetModuleRefPipe implements PipeTransform {
standalone: true,
})
export class GetComponentPipe implements PipeTransform {
+ constructor(private readonly contextService: RendererContextService) {}
+
transform(componentName: string): Type | null {
- return componentName ? getComponent(componentName) : null;
+ return componentName ? getComponent(componentName, this.contextService.getContext()) : null;
}
}
@@ -71,6 +76,7 @@ export class IsStringPipe implements PipeTransform {
GetDirectivesPipe,
ComponentOutlet,
ParseDataPipe,
+ ApplyDefaultPropsPipe,
MergeObjectPipe,
AutoApplyDirectivesPipe,
],
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer.component.html b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer.component.html
index 3e746a7c..10fcd171 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer.component.html
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/src/renderer.component.html
@@ -29,7 +29,7 @@
| null {
- return this.componentName ? getComponent(this.componentName) : null;
+ return this.componentName ? getComponent(this.componentName, this.context) : null;
}
get moduleRef() {
- return this.componentName ? getModuleRef(this.componentName) : undefined;
+ return this.componentName ? getModuleRef(this.componentName, this.context) : undefined;
}
diff --git a/projects/tiny-schema-renderer-ng/projects/renderer/tsconfig.spec.json b/projects/tiny-schema-renderer-ng/projects/renderer/tsconfig.spec.json
index 077fdc2e..05a5ed0d 100644
--- a/projects/tiny-schema-renderer-ng/projects/renderer/tsconfig.spec.json
+++ b/projects/tiny-schema-renderer-ng/projects/renderer/tsconfig.spec.json
@@ -10,6 +10,6 @@
},
"include": [
"src/**/*.d.ts",
- "src/**/*.spec.ts"
+ "__test__/**/*.spec.ts"
]
}
diff --git a/projects/tiny-schema-renderer-ng/src/app/app.ts b/projects/tiny-schema-renderer-ng/src/app/app.ts
index 7e05d76b..4bff58ea 100644
--- a/projects/tiny-schema-renderer-ng/src/app/app.ts
+++ b/projects/tiny-schema-renderer-ng/src/app/app.ts
@@ -1,29 +1,25 @@
import { Component, signal } from '@angular/core';
-import { RendererMain } from '../../projects/renderer/src/renderer-main';
import { FormsModule } from '@angular/forms';
-import { TiTextModule } from '@opentiny/ng';
-import { TiSelectModule } from '@opentiny/ng';
+import { RendererMain } from '../../projects/renderer/src/renderer-main';
+import { RENDERER_SETTINGS } from '../../projects/renderer/src/renderer-settings';
+import { materials } from './materials';
+
@Component({
selector: 'app-root',
templateUrl: './app.html',
standalone: true,
- imports: [RendererMain, FormsModule, TiTextModule, TiSelectModule],
+ imports: [RendererMain, FormsModule],
+ providers: [
+ {
+ provide: RENDERER_SETTINGS,
+ useValue: { materials },
+ },
+ ],
})
export class App {
schema = signal({});
- inputValue = ''
- selectValue = ''
- options = [
- { label: '中国', value: 'china' },
- { label: '美国', value: 'usa' },
- { label: '英国', value: 'uk' },
- ]
async ngOnInit() {
- this.schema.set(await import('../mock/schema.json').then(m => m.default));
- console.log('schema', this.schema());
- }
- log(...args: any[]) {
- console.log('app log', ...args);
+ this.schema.set(await import('../mock/schema.json').then((m) => m.default));
}
}
diff --git a/projects/tiny-schema-renderer-ng/src/app/materials/index.ts b/projects/tiny-schema-renderer-ng/src/app/materials/index.ts
new file mode 100644
index 00000000..ea409aff
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/src/app/materials/index.ts
@@ -0,0 +1 @@
+export * from './materials';
diff --git a/projects/tiny-schema-renderer-ng/src/app/materials/materials.ts b/projects/tiny-schema-renderer-ng/src/app/materials/materials.ts
new file mode 100644
index 00000000..5f47316a
--- /dev/null
+++ b/projects/tiny-schema-renderer-ng/src/app/materials/materials.ts
@@ -0,0 +1,114 @@
+import { type Type } from '@angular/core';
+import {
+ TiButtonComponent,
+ TiButtonModule,
+ TiCardComponent,
+ TiCardHeaderComponent,
+ TiCardModule,
+ TiCheckboxComponent,
+ TiCheckboxGroupComponent,
+ TiCheckboxModule,
+ TiDateComponent,
+ TiDateModule,
+ TiDateRangeComponent,
+ TiDateRangeModule,
+ TiFormfieldComponent,
+ TiFormfieldModule,
+ TiItemComponent,
+ TiModalComponent,
+ TiModalModule,
+ TiPaginationComponent,
+ TiPaginationModule,
+ TiRadioComponent,
+ TiRadioGroupComponent,
+ TiRadioModule,
+ TiRateComponent,
+ TiRateModule,
+ TiSelectComponent,
+ TiSelectModule,
+ TiSliderComponent,
+ TiSliderModule,
+ TiSwitchComponent,
+ TiSwitchModule,
+ TiTabComponent,
+ TiTableComponent,
+ TiTableModule,
+ TiTabModule,
+ TiTabsComponent,
+ TiTextareaComponent,
+ TiTextareaModule,
+ TiTextComponent,
+ TiTextModule,
+ TiTipDirective,
+ TiUploadComponent,
+ TiUploadModule,
+} from '@opentiny/ng';
+import type { IRendererMaterials } from '../../../projects/renderer/src/renderer-materials';
+
+(TiTextComponent['ɵcmp'] as any).selectors[0][0] = 'input';
+(TiTextareaComponent['ɵcmp'] as any).selectors[0][0] = 'textarea';
+(TiRadioComponent['ɵcmp'] as any).selectors[0][0] = 'input';
+(TiCheckboxComponent['ɵcmp'] as any).selectors[0][0] = 'input';
+
+const components: Record> = {
+ TiButton: TiButtonComponent,
+ TiSelect: TiSelectComponent,
+ TiText: TiTextComponent,
+ TiTable: TiTableComponent,
+ TiModal: TiModalComponent,
+ TiDate: TiDateComponent,
+ TiPagination: TiPaginationComponent,
+ TiTabs: TiTabsComponent,
+ TiTab: TiTabComponent,
+ TiCheckbox: TiCheckboxComponent,
+ TiCheckboxGroup: TiCheckboxGroupComponent,
+ TiRadio: TiRadioComponent,
+ TiRadioGroup: TiRadioGroupComponent,
+ TiSwitch: TiSwitchComponent,
+ TiCard: TiCardComponent,
+ TiUpload: TiUploadComponent,
+ TiFormField: TiFormfieldComponent,
+ TiCardHeader: TiCardHeaderComponent,
+ TiItem: TiItemComponent,
+ TiDateRange: TiDateRangeComponent,
+ TiSlider: TiSliderComponent,
+ TiRate: TiRateComponent,
+ TiTextArea: TiTextareaComponent,
+};
+
+const modules: Record> = {
+ TiButton: TiButtonModule,
+ TiSelect: TiSelectModule,
+ TiText: TiTextModule,
+ TiTable: TiTableModule,
+ TiModal: TiModalModule,
+ TiDate: TiDateModule,
+ TiPagination: TiPaginationModule,
+ TiTabs: TiTabModule,
+ TiTab: TiTabModule,
+ TiCheckbox: TiCheckboxModule,
+ TiCheckboxGroup: TiCheckboxModule,
+ TiRadio: TiRadioModule,
+ TiRadioGroup: TiRadioModule,
+ TiSwitch: TiSwitchModule,
+ TiCard: TiCardModule,
+ TiUpload: TiUploadModule,
+ TiFormField: TiFormfieldModule,
+ TiCardHeader: TiCardModule,
+ TiItem: TiFormfieldModule,
+ TiDateRange: TiDateRangeModule,
+ TiSlider: TiSliderModule,
+ TiRate: TiRateModule,
+ TiTextArea: TiTextareaModule,
+};
+
+const directives: Record> = {
+ TiTip: TiTipDirective,
+};
+
+export const materials: IRendererMaterials = {
+ components,
+ modules,
+ directives,
+ autoApplyDirectives: {},
+};
diff --git a/scripts/ci-replace-workspace-deps.js b/scripts/ci-replace-workspace-deps.js
new file mode 100644
index 00000000..fcabb0ad
--- /dev/null
+++ b/scripts/ci-replace-workspace-deps.js
@@ -0,0 +1,189 @@
+#!/usr/bin/env node
+
+const fs = require('fs');
+const path = require('path');
+const { execFileSync } = require('child_process');
+
+const WORKSPACE_PROTOCOL = /^workspace:/;
+const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
+const REPO_ROOT = path.resolve(__dirname, '..');
+const WORKSPACE_ROOTS = ['packages', 'sites', 'docs', 'projects'];
+
+function readJson(filePath) {
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
+}
+
+function collectPackageJsonFiles(dir, results = []) {
+ if (!fs.existsSync(dir)) {
+ return results;
+ }
+
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
+ if (!entry.isDirectory() || entry.name === 'node_modules' || entry.name === 'dist') {
+ continue;
+ }
+
+ const fullDir = path.join(dir, entry.name);
+ const pkgJsonPath = path.join(fullDir, 'package.json');
+
+ if (fs.existsSync(pkgJsonPath)) {
+ results.push(pkgJsonPath);
+ }
+
+ collectPackageJsonFiles(fullDir, results);
+ }
+
+ return results;
+}
+
+function loadWorkspacePackageNames() {
+ const names = new Set();
+
+ for (const root of WORKSPACE_ROOTS) {
+ for (const pkgJsonPath of collectPackageJsonFiles(path.join(REPO_ROOT, root))) {
+ const pkg = readJson(pkgJsonPath);
+ if (pkg.name) {
+ names.add(pkg.name);
+ }
+ }
+ }
+
+ return names;
+}
+
+function parseListEnv(name) {
+ const value = process.env[name];
+ if (!value) {
+ return [];
+ }
+ return value
+ .split(',')
+ .map((item) => item.trim())
+ .filter(Boolean);
+}
+
+function fetchNpmVersion(packageName, tag, registry = DEFAULT_REGISTRY) {
+ const spec = tag === 'latest' ? packageName : `${packageName}@${tag}`;
+
+ try {
+ const output = execFileSync('npm', ['view', spec, 'version', '--registry', registry], {
+ encoding: 'utf8',
+ stdio: ['ignore', 'pipe', 'pipe'],
+ }).trim();
+
+ const version = output.split('\n').pop().trim().replace(/^"|"$/g, '');
+ if (!version) {
+ throw new Error('npm view 未返回 version');
+ }
+ return version;
+ } catch (error) {
+ const detail = (error.stderr?.toString?.() || error.stdout?.toString?.() || error.message || String(error)).trim();
+ if (/404|E404|Not Found|is not in this registry/i.test(detail)) {
+ throw new Error(`npm 上未找到 ${packageName}@${tag}`);
+ }
+ throw new Error(`无法从 npm 读取 ${packageName}@${tag}:${detail}`);
+ }
+}
+
+function getDependencyFields(pkg) {
+ return ['dependencies', 'peerDependencies'].filter(
+ (field) => pkg[field] && typeof pkg[field] === 'object',
+ );
+}
+
+function collectWorkspaceDeps(pkg, workspacePackageNames) {
+ const deps = [];
+
+ for (const field of getDependencyFields(pkg)) {
+ for (const [depName, versionRange] of Object.entries(pkg[field])) {
+ if (!WORKSPACE_PROTOCOL.test(versionRange) || !workspacePackageNames.has(depName)) {
+ continue;
+ }
+ deps.push({ depName, field, versionRange });
+ }
+ }
+
+ return deps;
+}
+
+function resolveDepVersion(depName, publishNames, publishVersion, npmTag) {
+ if (publishNames.has(depName) && publishVersion) {
+ return { version: publishVersion, source: `同批发布 @ ${publishVersion}` };
+ }
+ return { version: fetchNpmVersion(depName, npmTag), source: `npm@${npmTag}` };
+}
+
+function replaceWorkspaceDeps(pkgPathArg, workspacePackageNames, publishNames, publishVersion, npmTag) {
+ const pkgPath = path.resolve(process.cwd(), pkgPathArg);
+ if (!fs.existsSync(pkgPath)) {
+ throw new Error(`File not found: ${pkgPath}`);
+ }
+
+ const pkg = readJson(pkgPath);
+ const workspaceDeps = collectWorkspaceDeps(pkg, workspacePackageNames);
+
+ if (workspaceDeps.length === 0) {
+ console.log(`${pkgPathArg}:无需替换 workspace 依赖`);
+ return;
+ }
+
+ const updates = [];
+
+ for (const { depName, field, versionRange } of workspaceDeps) {
+ const { version, source } = resolveDepVersion(depName, publishNames, publishVersion, npmTag);
+ updates.push({ depName, field, from: versionRange, to: version, source });
+ pkg[field][depName] = version;
+ }
+
+ for (const item of updates) {
+ console.log(`${item.depName}: ${item.from} -> ${item.to} (${item.source})`);
+ }
+
+ fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8');
+ console.log(`Updated ${pkgPathArg}`);
+}
+
+function main() {
+ const publishPkgJsons = parseListEnv('PUBLISH_PKG_JSONS');
+ const fetchNpmTag = process.env.FETCH_NPM_TAG || 'latest';
+ const publishVersion = process.env.PUBLISH_VERSION || '';
+
+ if (publishPkgJsons.length === 0) {
+ console.error(`Usage:
+ PUBLISH_PKG_JSONS=packages/server/package.json,... node scripts/ci-replace-workspace-deps.js
+
+环境变量:
+ PUBLISH_PKG_JSONS 本次发布的 package.json 路径(逗号分隔)
+ FETCH_NPM_TAG 从 npm 拉取依赖版本的 tag,默认 latest
+ PUBLISH_VERSION 多包同批发布时传入,与 workflow 输入的版本号一致
+
+规则:
+ - 依赖也在 PUBLISH_PKG_JSONS 且设置了 PUBLISH_VERSION → 用 PUBLISH_VERSION
+ - 其余 workspace 内部依赖 → 从 npm@FETCH_NPM_TAG 拉取(默认 latest)
+ - 单包发布时不设 PUBLISH_VERSION,依赖一律走 npm
+`);
+ process.exit(1);
+ }
+
+ try {
+ const workspacePackageNames = loadWorkspacePackageNames();
+ const publishNames = new Set(
+ publishPkgJsons.map((pkgJsonPath) => {
+ const pkg = readJson(path.resolve(process.cwd(), pkgJsonPath));
+ if (!pkg.name) {
+ throw new Error(`${pkgJsonPath} 缺少 name 字段`);
+ }
+ return pkg.name;
+ }),
+ );
+
+ for (const pkgJsonPath of publishPkgJsons) {
+ replaceWorkspaceDeps(pkgJsonPath, workspacePackageNames, publishNames, publishVersion, fetchNpmTag);
+ }
+ } catch (error) {
+ console.error(error instanceof Error ? error.message : error);
+ process.exit(1);
+ }
+}
+
+main();
diff --git a/scripts/skill-sync.mjs b/scripts/skill-sync.mjs
new file mode 100644
index 00000000..5cbee383
--- /dev/null
+++ b/scripts/skill-sync.mjs
@@ -0,0 +1,610 @@
+#!/usr/bin/env node
+
+import { platform } from 'os';
+import { join, isAbsolute, resolve, dirname, relative } from 'path';
+import { readFileSync, existsSync, constants } from 'fs';
+import {
+ cp,
+ lstat,
+ mkdir,
+ readdir,
+ readFile,
+ rename,
+ rm,
+ symlink,
+ access,
+} from 'fs/promises';
+
+const SYNCABLE_TOOL_IDS = [
+ 'claude',
+ 'cursor',
+ 'gemini',
+ 'codex',
+ 'opencode',
+ 'hermes',
+ 'openclaw',
+];
+
+const DEFAULT_CONFIG = {
+ ssotDir: '.agents/skills',
+ syncMethod: 'auto',
+ enabledTools: ['claude', 'cursor', 'gemini', 'codex', 'opencode', 'hermes', 'openclaw'],
+ overrides: {
+ claude_config_dir: '.claude',
+ cursor_config_dir: '.cursor',
+ gemini_config_dir: '.gemini',
+ codex_config_dir: '.codex',
+ opencode_config_dir: '.config/opencode',
+ hermes_config_dir: '.hermes',
+ openclaw_config_dir: '.openclaw',
+ },
+};
+
+const TOOL_REGISTRY = {
+ claude: { overrideKey: 'claude_config_dir', defaultConfigRoot: ['.claude'] },
+ cursor: { overrideKey: 'cursor_config_dir', defaultConfigRoot: ['.cursor'] },
+ gemini: { overrideKey: 'gemini_config_dir', defaultConfigRoot: ['.gemini'] },
+ codex: { overrideKey: 'codex_config_dir', defaultConfigRoot: ['.codex'] },
+ opencode: { overrideKey: 'opencode_config_dir', defaultConfigRoot: ['.config', 'opencode'] },
+ hermes: { overrideKey: 'hermes_config_dir', defaultConfigRoot: ['.hermes'] },
+ openclaw: { overrideKey: 'openclaw_config_dir', defaultConfigRoot: ['.openclaw'] },
+};
+
+function isPathInside(child, parent) {
+ const rel = relative(resolve(parent), resolve(child));
+ return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
+}
+
+function resolveProjectPath(raw, projectRoot, label = 'Path') {
+ const trimmed = raw.trim();
+ if (trimmed === '~' || trimmed.startsWith('~/') || trimmed.startsWith('~\\')) {
+ throw new Error(`${label} must be inside the project (home paths are not allowed): ${raw}`);
+ }
+
+ const candidate = isAbsolute(trimmed) ? resolve(trimmed) : resolve(projectRoot, trimmed);
+ const resolved = resolve(candidate);
+ if (!isPathInside(resolved, projectRoot)) {
+ throw new Error(`${label} escapes project root: ${raw} → ${resolved}`);
+ }
+ return resolved;
+}
+
+function resolveOverridePath(raw, projectRoot) {
+ return resolveProjectPath(raw, projectRoot, 'Override path');
+}
+
+function getOverrideDir(toolId, overrides = {}, projectRoot = process.cwd()) {
+ const config = TOOL_REGISTRY[toolId];
+ if (!config?.overrideKey) return null;
+ const raw = overrides[config.overrideKey]?.trim();
+ if (!raw) return null;
+ return resolveOverridePath(raw, projectRoot);
+}
+
+function getAppSkillsDir(toolId, overrides = {}, projectRoot = process.cwd()) {
+ const config = TOOL_REGISTRY[toolId];
+ if (!config) throw new Error(`Unknown tool: ${toolId}`);
+
+ const override = getOverrideDir(toolId, overrides, projectRoot);
+ if (override) return join(override, 'skills');
+
+ return join(projectRoot, ...config.defaultConfigRoot, 'skills');
+}
+
+function resolveSsotDir(ssotDir, projectRoot = process.cwd()) {
+ return resolveProjectPath(ssotDir, projectRoot, 'SSOT path');
+}
+
+function getAllScanSources(overrides = {}, ssotDir, projectRoot = process.cwd(), enabledTools = []) {
+ const sources = enabledTools.map((toolId) => ({
+ toolId,
+ path: getAppSkillsDir(toolId, overrides, projectRoot),
+ }));
+ if (ssotDir) sources.push({ toolId: 'ssot', path: ssotDir });
+ return sources;
+}
+
+function loadConfig(configPath) {
+ if (!existsSync(configPath)) {
+ console.warn(`Config not found: ${configPath}, using built-in defaults`);
+ return DEFAULT_CONFIG;
+ }
+ return JSON.parse(readFileSync(configPath, 'utf-8'));
+}
+
+function resolveConfig(config, projectRoot = process.cwd()) {
+ return {
+ ssotDir: resolveSsotDir(config.ssotDir ?? DEFAULT_CONFIG.ssotDir, projectRoot),
+ syncMethod: config.syncMethod ?? 'auto',
+ enabledTools: (config.enabledTools ?? DEFAULT_CONFIG.enabledTools).filter((id) =>
+ SYNCABLE_TOOL_IDS.includes(id),
+ ),
+ overrides: { ...DEFAULT_CONFIG.overrides, ...(config.overrides ?? {}) },
+ projectRoot,
+ };
+}
+
+async function pathExists(path) {
+ try {
+ await access(path);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+async function isSymlink(path) {
+ try {
+ return (await lstat(path)).isSymbolicLink();
+ } catch {
+ return false;
+ }
+}
+
+async function validateSkillSource(source, directory) {
+ if (!(await pathExists(source))) {
+ throw new Error(`Skill not found in SSOT: ${directory}`);
+ }
+ try {
+ await access(join(source, 'SKILL.md'), constants.F_OK);
+ } catch {
+ throw new Error(`Skill source missing SKILL.md, refusing sync: ${source}`);
+ }
+}
+
+async function removePath(path) {
+ if (!(await pathExists(path))) return;
+
+ if (await isSymlink(path)) {
+ await rm(path, platform() === 'win32' ? { recursive: true } : undefined);
+ return;
+ }
+
+ const stat = await lstat(path);
+ await rm(path, stat.isDirectory() ? { recursive: true } : undefined);
+}
+
+async function replaceDestWithCopy(source, dest, directory) {
+ await validateSkillSource(source, directory);
+
+ const parent = dirname(dest);
+ await mkdir(parent, { recursive: true });
+
+ const safeName = directory.replace(/[^a-zA-Z0-9_-]/g, '_');
+ const tmp = join(parent, `.${safeName}.tmp-${process.pid}-${Date.now()}`);
+
+ if (await pathExists(tmp)) await removePath(tmp);
+
+ try {
+ await cp(source, tmp, { recursive: true, force: true });
+ if (await pathExists(dest)) await removePath(dest);
+ await rename(tmp, dest);
+ } catch (err) {
+ if (await pathExists(tmp)) await removePath(tmp);
+ throw err;
+ }
+}
+
+async function replaceDestWithSymlink(source, dest, directory) {
+ const parent = dirname(dest);
+ await mkdir(parent, { recursive: true });
+
+ const safeName = directory.replace(/[^a-zA-Z0-9_-]/g, '_');
+ const stamp = `${process.pid}-${Date.now()}`;
+ const tmp = join(parent, `.${safeName}.link-${stamp}`);
+ const bak = join(parent, `.${safeName}.bak-${stamp}`);
+
+ if (await pathExists(tmp)) await removePath(tmp);
+ if (await pathExists(bak)) await removePath(bak);
+
+ try {
+ await symlink(source, tmp, 'dir');
+ const destExists = (await pathExists(dest)) || (await isSymlink(dest));
+ if (destExists) await rename(dest, bak);
+ try {
+ await rename(tmp, dest);
+ } catch (err) {
+ if (destExists && (await pathExists(bak))) await rename(bak, dest);
+ throw err;
+ }
+ if (await pathExists(bak)) await removePath(bak);
+ } catch (err) {
+ if (await pathExists(tmp)) await removePath(tmp);
+ throw err;
+ }
+}
+
+async function syncSkillToTool({
+ ssotDir,
+ directory,
+ toolId,
+ method,
+ overrides = {},
+ projectRoot = process.cwd(),
+}) {
+ const source = join(ssotDir, directory);
+ await validateSkillSource(source, directory);
+
+ const appDir = getAppSkillsDir(toolId, overrides, projectRoot);
+ await mkdir(appDir, { recursive: true });
+ const dest = join(appDir, directory);
+
+ if (method === 'copy') {
+ await replaceDestWithCopy(source, dest, directory);
+ return { toolId, directory, method: 'copy' };
+ }
+
+ if (method === 'symlink') {
+ await replaceDestWithSymlink(source, dest, directory);
+ return { toolId, directory, method: 'symlink' };
+ }
+
+ if ((await pathExists(dest)) && !(await isSymlink(dest))) {
+ await replaceDestWithCopy(source, dest, directory);
+ return { toolId, directory, method: 'copy', reason: 'dest-not-symlink' };
+ }
+
+ if (await isSymlink(dest)) await removePath(dest);
+
+ try {
+ await symlink(source, dest, 'dir');
+ return { toolId, directory, method: 'symlink' };
+ } catch (err) {
+ await replaceDestWithCopy(source, dest, directory);
+ return { toolId, directory, method: 'copy', reason: 'symlink-fallback', error: err.message };
+ }
+}
+
+async function syncAllSkills({ ssotDir, enabledTools, syncMethod, overrides, projectRoot }) {
+ const directories = await listSkillDirectories(ssotDir);
+ const ssotSet = new Set(directories);
+ const results = [];
+
+ for (const directory of directories) {
+ for (const toolId of enabledTools) {
+ try {
+ results.push(
+ await syncSkillToTool({
+ ssotDir,
+ directory,
+ toolId,
+ method: syncMethod,
+ overrides,
+ projectRoot,
+ }),
+ );
+ } catch (err) {
+ results.push({
+ toolId,
+ directory,
+ method: 'error',
+ error: err instanceof Error ? err.message : String(err),
+ });
+ }
+ }
+ }
+
+ for (const toolId of enabledTools) {
+ const appDir = getAppSkillsDir(toolId, overrides, projectRoot);
+ for (const skill of await listSkillEntries(appDir)) {
+ if (ssotSet.has(skill.directory)) continue;
+ const dest = join(appDir, skill.directory);
+ try {
+ await removePath(dest);
+ results.push({ toolId, directory: skill.directory, method: 'removed' });
+ } catch (err) {
+ results.push({
+ toolId,
+ directory: skill.directory,
+ method: 'error',
+ error: err instanceof Error ? err.message : String(err),
+ });
+ }
+ }
+ }
+
+ return results;
+}
+
+function parseSkillFrontmatter(content) {
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
+ if (!match) return {};
+
+ const result = {};
+ const lines = match[1].split('\n');
+
+ for (let i = 0; i < lines.length; i++) {
+ const kv = lines[i].match(/^(\w+):\s*(.*)$/);
+ if (!kv) continue;
+
+ const key = kv[1];
+ let value = kv[2].trim();
+
+ if (value === '>-' || value === '|' || value === '>') {
+ const folded = [];
+ while (
+ i + 1 < lines.length &&
+ /^(\s|$)/.test(lines[i + 1]) &&
+ !/^\w+:/.test(lines[i + 1])
+ ) {
+ i++;
+ folded.push(lines[i].trim());
+ }
+ value = folded.join(' ').trim();
+ } else {
+ value = value.replace(/^["']|["']$/g, '');
+ }
+
+ if (value) result[key] = value;
+ }
+
+ return result;
+}
+
+async function listSkillEntries(dirPath) {
+ try {
+ await access(dirPath, constants.F_OK);
+ } catch {
+ return [];
+ }
+
+ const entries = await readdir(dirPath, { withFileTypes: true });
+ const skills = [];
+
+ for (const entry of entries) {
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
+ if (entry.name.startsWith('.')) continue;
+
+ const skillPath = join(dirPath, entry.name);
+ try {
+ await access(join(skillPath, 'SKILL.md'), constants.F_OK);
+ } catch {
+ continue;
+ }
+
+ let name = entry.name;
+ let description;
+
+ try {
+ const parsed = parseSkillFrontmatter(await readFile(join(skillPath, 'SKILL.md'), 'utf-8'));
+ name = parsed.name ?? name;
+ description = parsed.description;
+ } catch {
+ // keep defaults
+ }
+
+ skills.push({ directory: entry.name, name, description, path: skillPath });
+ }
+
+ return skills;
+}
+
+async function listSkillDirectories(ssotDir) {
+ return (await listSkillEntries(ssotDir)).map((e) => e.directory);
+}
+
+async function scanSkills({
+ ssotDir,
+ overrides = {},
+ projectRoot = process.cwd(),
+ enabledTools = [],
+}) {
+ const sources = getAllScanSources(overrides, ssotDir, projectRoot, enabledTools);
+ const ssotSkills = new Set((await listSkillEntries(ssotDir)).map((s) => s.directory));
+ const aggregated = new Map();
+
+ for (const { toolId, path } of sources) {
+ for (const skill of await listSkillEntries(path)) {
+ const existing = aggregated.get(skill.directory);
+ if (existing) {
+ if (toolId !== 'ssot' && !existing.foundIn.includes(toolId)) {
+ existing.foundIn.push(toolId);
+ }
+ if (!existing.locations.find((l) => l.toolId === toolId)) {
+ existing.locations.push({ toolId, path: skill.path });
+ }
+ } else {
+ aggregated.set(skill.directory, {
+ directory: skill.directory,
+ name: skill.name,
+ description: skill.description,
+ foundIn: toolId !== 'ssot' ? [toolId] : [],
+ inSsot: ssotSkills.has(skill.directory),
+ locations: [{ toolId, path: skill.path }],
+ });
+ }
+ }
+ }
+
+ return [...aggregated.values()].sort((a, b) => a.directory.localeCompare(b.directory));
+}
+
+async function getSyncStatus({ ssotDir, enabledTools, overrides, projectRoot = process.cwd() }) {
+ const status = [];
+
+ for (const skill of await listSkillEntries(ssotDir)) {
+ const toolStatus = [];
+
+ for (const toolId of enabledTools) {
+ const dest = join(getAppSkillsDir(toolId, overrides, projectRoot), skill.directory);
+ const exists = await pathExists(dest);
+ const symlinked = exists ? await isSymlink(dest) : false;
+
+ toolStatus.push({
+ toolId,
+ path: dest,
+ exists,
+ type: !exists ? 'missing' : symlinked ? 'symlink' : 'copy',
+ });
+ }
+
+ status.push({
+ directory: skill.directory,
+ name: skill.name,
+ ssotPath: skill.path,
+ tools: toolStatus,
+ });
+ }
+
+ return status;
+}
+
+function findConfigPath(args) {
+ const configIdx = args.indexOf('--config');
+ if (configIdx !== -1 && args[configIdx + 1]) return resolve(args[configIdx + 1]);
+ return resolve(process.cwd(), 'skills-sync.config.json');
+}
+
+function printUsage() {
+ console.log(`Usage: node scripts/skill-sync.mjs [command] [options]
+
+Commands:
+ (default) Run scan → sync → status
+ all Same as default
+ sync Sync SSOT skills to AI platform directories
+ scan Scan SSOT and platform directories for skills
+ status Show sync status (symlink/copy/missing) per skill
+
+Options:
+ --config Config file (default: ./skills-sync.config.json)
+`);
+}
+
+const SUBCOMMANDS = new Set(['scan', 'sync', 'status', 'all']);
+
+function parseCommand(args) {
+ const first = args[0];
+ if (first === '--help' || first === '-h') return { type: 'help' };
+ if (!first || !SUBCOMMANDS.has(first)) return { type: 'run', command: 'all' };
+ return { type: 'run', command: first };
+}
+
+async function cmdAll(config) {
+ await cmdScan(config);
+ console.log('');
+ await cmdSync(config);
+ console.log('');
+ await cmdStatus(config);
+}
+
+async function cmdSync(config) {
+ const results = await syncAllSkills({
+ ssotDir: config.ssotDir,
+ enabledTools: config.enabledTools,
+ syncMethod: config.syncMethod,
+ overrides: config.overrides,
+ projectRoot: config.projectRoot,
+ });
+
+ const failed = results.filter((r) => r.method === 'error');
+ const removed = results.filter((r) => r.method === 'removed');
+ const synced = results.filter((r) => r.method !== 'error' && r.method !== 'removed');
+
+ console.log(
+ `Synced ${synced.length} skill×tool projection(s) (method: ${config.syncMethod}` +
+ (removed.length ? `, ${removed.length} removed` : '') +
+ (failed.length ? `, ${failed.length} failed` : '') +
+ ')',
+ );
+ for (const r of results) {
+ if (r.method === 'error') {
+ console.log(` ✗ ${r.directory} → ${r.toolId} [error] ${r.error}`);
+ continue;
+ }
+ if (r.method === 'removed') {
+ console.log(` − ${r.directory} → ${r.toolId} [removed]`);
+ continue;
+ }
+ const extra = r.reason ? ` (${r.reason})` : '';
+ console.log(` ✓ ${r.directory} → ${r.toolId} [${r.method}]${extra}`);
+ }
+
+ if (failed.length) {
+ throw new Error(`${failed.length} skill×tool projection(s) failed`);
+ }
+}
+
+async function cmdScan(config) {
+ const results = await scanSkills({
+ ssotDir: config.ssotDir,
+ overrides: config.overrides,
+ projectRoot: config.projectRoot,
+ enabledTools: config.enabledTools,
+ });
+
+ console.log(`Found ${results.length} skill(s):`);
+ for (const s of results) {
+ const ssot = s.inSsot ? 'SSOT' : 'external';
+ const tools = s.foundIn.length ? s.foundIn.join(', ') : 'none';
+ console.log(` • ${s.directory} (${s.name}) [${ssot}] platforms: ${tools}`);
+ }
+}
+
+async function cmdStatus(config) {
+ const status = await getSyncStatus({
+ ssotDir: config.ssotDir,
+ enabledTools: config.enabledTools,
+ overrides: config.overrides,
+ projectRoot: config.projectRoot,
+ });
+
+ console.log(`SSOT: ${config.ssotDir}`);
+ console.log(`Enabled tools: ${config.enabledTools.join(', ')}`);
+ console.log('');
+
+ if (status.length === 0) {
+ console.log('No skills in SSOT.');
+ return;
+ }
+
+ for (const s of status) {
+ console.log(`${s.directory} (${s.name})`);
+ for (const t of s.tools) {
+ const icon = t.type === 'missing' ? '✗' : t.type === 'symlink' ? '↗' : '⎘';
+ console.log(` ${icon} ${t.toolId}: ${t.type} → ${t.path}`);
+ }
+ }
+}
+
+async function main() {
+ const args = process.argv.slice(2);
+ const parsed = parseCommand(args);
+
+ if (parsed.type === 'help') {
+ printUsage();
+ process.exit(0);
+ }
+
+ const configPath = findConfigPath(args);
+ const projectRoot = process.cwd();
+
+ let config;
+ try {
+ config = resolveConfig(loadConfig(configPath), projectRoot);
+ } catch (err) {
+ console.error(`Error: ${err.message}`);
+ process.exit(1);
+ }
+
+ try {
+ switch (parsed.command) {
+ case 'all':
+ await cmdAll(config);
+ break;
+ case 'sync':
+ await cmdSync(config);
+ break;
+ case 'scan':
+ await cmdScan(config);
+ break;
+ case 'status':
+ await cmdStatus(config);
+ break;
+ }
+ } catch (err) {
+ console.error(`Error: ${err.message}`);
+ process.exit(1);
+ }
+}
+
+main();
diff --git a/sites/homepage/web/package.json b/sites/homepage/web/package.json
index 326e6ceb..ea943135 100644
--- a/sites/homepage/web/package.json
+++ b/sites/homepage/web/package.json
@@ -20,7 +20,7 @@
"@opentiny/vue-tag": "~3.28.0",
"@opentiny/vue-tooltip": "~3.28.0",
"highlight.js": "^11.5.1",
- "vue": "~3.4.32"
+ "vue": "^3.5.18"
},
"devDependencies": {
"@opentiny/vue-vite-import": "^1.2.0",
diff --git a/sites/homepage/web/src/App.vue b/sites/homepage/web/src/App.vue
index 9d29dac7..e552d1b0 100644
--- a/sites/homepage/web/src/App.vue
+++ b/sites/homepage/web/src/App.vue
@@ -1,24 +1,28 @@
-
+
+
diff --git a/sites/homepage/web/src/components/HomeExtend.vue b/sites/homepage/web/src/components/HomeExtend.vue
index b7ef02db..9baab541 100644
--- a/sites/homepage/web/src/components/HomeExtend.vue
+++ b/sites/homepage/web/src/components/HomeExtend.vue
@@ -1,25 +1,16 @@
+
+
+
+
+ {{ t('lang.zh') }}
+
+ |
+
+ {{ t('lang.en') }}
+
+
+
+
+
diff --git a/sites/homepage/web/src/i18n/en.json b/sites/homepage/web/src/i18n/en.json
new file mode 100644
index 00000000..31c01d22
--- /dev/null
+++ b/sites/homepage/web/src/i18n/en.json
@@ -0,0 +1,110 @@
+{
+ "lang": {
+ "switch": "Language",
+ "zh": "中文",
+ "en": "EN"
+ },
+ "hero": {
+ "title": "OpenTiny GenUI SDK",
+ "subtitle": "Enhance LLM conversation display and interaction",
+ "description": "Deliver a seamless intelligent experience for users and powerful customization with ecosystem compatibility for developers",
+ "devDoc": "Docs",
+ "playground": "Playground",
+ "github": "GitHub"
+ },
+ "ability": {
+ "visual": {
+ "title": "Beyond text expression",
+ "subtitle": "Rebuild text with UI, break expression barriers, and unlock information value through visual interfaces"
+ },
+ "interaction": {
+ "title": "Smoother interaction",
+ "subtitle": "Break the two-step interaction pattern and enable one-stop flow from UI to conversation"
+ },
+ "mcp": {
+ "title": "MCP tools for real business scenarios",
+ "subtitle": "After MCP integration, when tool calls lack parameters, the model can auto-generate interactive UI to collect required information",
+ "mobileTitleLine1": "MCP tools",
+ "mobileTitleLine2": "for real business scenarios",
+ "parameters": "Parameters"
+ },
+ "stream": {
+ "title": "Mixed layout & streaming render",
+ "subtitle": "Non-intrusive GenUI integration with mixed layout and streaming UI rendering—no long waits for the interface"
+ }
+ },
+ "extend": {
+ "title": "Unlock more possibilities",
+ "calculator": "Calculator",
+ "todoApp": "Todo App",
+ "tryPlayground": "Try it in Playground",
+ "replayControls": "Playback controls",
+ "pause": "Pause",
+ "resume": "Resume",
+ "preparing": "Preparing playback",
+ "replay": "Replay",
+ "play": "Play",
+ "prompt": {
+ "element": "Generate a calculator without buttons, use div elements, macaron colors, no TinyLayout, make it beautiful",
+ "page": "Create a rich todo app with as many features as you can think of",
+ "elementBubble": "Generate a calculator with div elements, macaron colors, make it beautiful",
+ "pageBubble": "Create a rich todo app with as many features as you can think of"
+ }
+ },
+ "guide": {
+ "title": "Integrate GenUI quickly",
+ "subtitle": "Powerful renderer components and ready-to-use chat components",
+ "devDoc": "Documentation",
+ "step1": {
+ "title": "Step 1: Import and use the chat component",
+ "description": "The out-of-the-box chat component includes conversation UI and message management",
+ "mobile": "Import"
+ },
+ "step2": {
+ "title": "Step 2: Use the chat component",
+ "description": "Configure your LLM service endpoint and experience GenUI right away",
+ "mobile": "Use chat"
+ },
+ "step3": {
+ "title": "Step 3: Add custom configuration",
+ "description": "Powerful customization for theme, components, message toolbar, and more",
+ "mobile": "Customize"
+ }
+ },
+ "feature": {
+ "title": "Built for developers",
+ "subtitle": "OpenTiny GenUI offers rich features and strong ecosystem compatibility",
+ "compatible": {
+ "title": "AI ecosystem compatibility",
+ "description": "OpenAI-format compatible with MCP service integration"
+ },
+ "theme": {
+ "title": "Custom themes",
+ "description": "Theme switching, eye-friendly dark mode, and user customization for different needs"
+ },
+ "component": {
+ "title": "Custom components",
+ "description": "Pass custom components and descriptions to enhance GenUI and enrich generated interfaces"
+ },
+ "action": {
+ "title": "Custom interactions",
+ "description": "Custom behaviors such as opening pages, downloading attachments, and more"
+ },
+ "stack": {
+ "title": "Multi-stack support",
+ "description": "Vue and Angular renderers, plus extensibility for custom tech stacks"
+ },
+ "more": {
+ "title": "More features",
+ "description": "Custom examples and snippets help build better UIs for diverse visual preferences"
+ }
+ },
+ "link": {
+ "title": "Try OpenTiny GenUI now",
+ "description": "Enhance LLM conversation display and interaction for a seamless intelligent experience",
+ "descriptionLine1": "Enhance LLM conversation display and interaction",
+ "descriptionLine2": "for a seamless intelligent experience",
+ "tryNow": "Try now",
+ "productDoc": "Product docs"
+ }
+}
diff --git a/sites/homepage/web/src/i18n/i18n.ts b/sites/homepage/web/src/i18n/i18n.ts
new file mode 100644
index 00000000..02f4590e
--- /dev/null
+++ b/sites/homepage/web/src/i18n/i18n.ts
@@ -0,0 +1,126 @@
+import { ref, reactive, readonly, UnwrapNestedRefs } from 'vue';
+import {
+ I18nInstance,
+ I18nMessages,
+ I18nOptions,
+ I18nMessageObject,
+ I18nTranslateParams,
+} from './types';
+
+export function createI18n(options: I18nOptions = {}): I18nInstance {
+ const defaultOptions: Required = {
+ locale: 'zh_CN',
+ messages: {},
+ };
+
+ const config: Required = {
+ ...defaultOptions,
+ ...options,
+ messages: { ...defaultOptions.messages, ...options.messages },
+ };
+
+ const locale = ref(config.locale);
+
+ const _messages = reactive>(
+ structuredClone(config.messages) as UnwrapNestedRefs,
+ );
+
+ function isPlainObject(value: unknown): value is Record {
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
+ }
+
+ function _deepMerge(target: I18nMessageObject, source: I18nMessageObject): I18nMessageObject {
+ if (!isPlainObject(target)) {
+ return structuredClone(source);
+ }
+
+ if (!isPlainObject(source)) {
+ return structuredClone(target);
+ }
+
+ for (const key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ const targetValue = target[key];
+ const sourceValue = source[key];
+
+ if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
+ target[key] = _deepMerge(
+ targetValue as I18nMessageObject,
+ sourceValue as I18nMessageObject,
+ );
+ } else {
+ target[key] = structuredClone(sourceValue);
+ }
+ }
+ }
+
+ return target;
+ }
+
+ function setLocale(lang: string): void {
+ if (typeof lang !== 'string' || lang.trim() === '') {
+ console.warn('语言标识必须是非空字符串!');
+ return;
+ }
+
+ const trimmedLang = lang.trim();
+ if (locale.value !== trimmedLang) {
+ locale.value = trimmedLang;
+ }
+ }
+
+ function mergeMessages(newMessages: I18nMessages, isCoverSameKey = false): void {
+ if (typeof newMessages !== 'object' || newMessages === null) {
+ console.warn('要合并的词条必须是合法对象!');
+ return;
+ }
+
+ for (const lang in newMessages) {
+ if (Object.prototype.hasOwnProperty.call(newMessages, lang)) {
+ const newLangMessages = newMessages[lang];
+ const existingLangMessages = _messages[lang];
+
+ if (!existingLangMessages || isCoverSameKey) {
+ _messages[lang] = structuredClone(newLangMessages) as I18nMessageObject;
+ } else {
+ _deepMerge(existingLangMessages, newLangMessages);
+ }
+ }
+ }
+ }
+
+ function t(key: string, params: I18nTranslateParams = {}): string {
+ if (typeof key !== 'string' || key.trim() === '') {
+ return '';
+ }
+
+ const trimmedKey = key.trim();
+ const currentLang = locale.value;
+ const currentLangMessages = _messages[currentLang] || {};
+
+ const rawText = trimmedKey.split('.').reduce((current: unknown, nextKey) => {
+ if (current && typeof current === 'object' && nextKey in (current as object)) {
+ return (current as Record)[nextKey];
+ }
+ return trimmedKey;
+ }, currentLangMessages as unknown);
+
+ if (typeof rawText !== 'string') {
+ return trimmedKey;
+ }
+
+ return rawText.replace(/\{(\w+)\}/g, (match, paramKey) => {
+ return Object.prototype.hasOwnProperty.call(params, paramKey)
+ ? String(params[paramKey])
+ : match;
+ });
+ }
+
+ return {
+ locale,
+ messages: readonly(_messages),
+ setLocale,
+ mergeMessages,
+ t,
+ };
+}
diff --git a/sites/homepage/web/src/i18n/index.ts b/sites/homepage/web/src/i18n/index.ts
new file mode 100644
index 00000000..9507bb1e
--- /dev/null
+++ b/sites/homepage/web/src/i18n/index.ts
@@ -0,0 +1,18 @@
+import zhCN from './zh.json';
+import enUS from './en.json';
+import { createI18n } from './i18n';
+
+const globalI18n = createI18n({
+ locale: 'zh_CN',
+ messages: {
+ zh_CN: zhCN,
+ en_US: enUS,
+ },
+});
+
+export const { t, locale, setLocale, mergeMessages, messages } = globalI18n;
+
+export const useI18n = () => globalI18n;
+
+export * from './i18n';
+export * from './types';
diff --git a/sites/homepage/web/src/i18n/types.ts b/sites/homepage/web/src/i18n/types.ts
new file mode 100644
index 00000000..7a2ce407
--- /dev/null
+++ b/sites/homepage/web/src/i18n/types.ts
@@ -0,0 +1,26 @@
+import { Reactive, Ref, UnwrapNestedRefs } from 'vue';
+
+export type I18nMessageObject = {
+ [key: string]: string | I18nMessageObject;
+};
+
+export type I18nMessages = {
+ [lang: string]: I18nMessageObject;
+};
+
+export type I18nTranslateParams = {
+ [key: string]: string | number | boolean;
+};
+
+export interface I18nOptions {
+ locale?: string;
+ messages?: I18nMessages;
+}
+
+export interface I18nInstance {
+ locale: Ref;
+ messages: Readonly>>;
+ setLocale: (lang: string) => void;
+ mergeMessages: (newMessages: I18nMessages, isCoverSameKey?: boolean) => void;
+ t: (key: string, params?: I18nTranslateParams) => string;
+}
diff --git a/sites/homepage/web/src/i18n/zh.json b/sites/homepage/web/src/i18n/zh.json
new file mode 100644
index 00000000..dd3798cc
--- /dev/null
+++ b/sites/homepage/web/src/i18n/zh.json
@@ -0,0 +1,110 @@
+{
+ "lang": {
+ "switch": "语言",
+ "zh": "中文",
+ "en": "EN"
+ },
+ "hero": {
+ "title": "OpenTiny GenUI SDK",
+ "subtitle": "增强大模型对话展示和交互",
+ "description": "为用户打造极致顺滑的智能体验,给开发者提供强大的定制能力与生态兼容性",
+ "devDoc": "开发文档",
+ "playground": "演练场",
+ "github": "GitHub"
+ },
+ "ability": {
+ "visual": {
+ "title": "超越文字的表达能力",
+ "subtitle": "以界面重构文字,打破文字表达壁垒,用可视化界面释放信息价值"
+ },
+ "interaction": {
+ "title": "更加流畅的交互方式",
+ "subtitle": "打破两步交互,实现界面到对话的一站式流转"
+ },
+ "mcp": {
+ "title": "结合MCP工具,让AI更懂业务场景",
+ "subtitle": "接入MCP工具后,模型在调用工具缺少参数时能自动生成交互式UI来收集所需信息",
+ "mobileTitleLine1": "结合MCP工具",
+ "mobileTitleLine2": "让AI更懂业务场景",
+ "parameters": "Parameters"
+ },
+ "stream": {
+ "title": "界面混排与流式渲染",
+ "subtitle": "生成式UI无侵入接入,支持混排,并实现UI流式渲染,界面无需漫长等待生成"
+ }
+ },
+ "extend": {
+ "title": "解锁更多玩法",
+ "calculator": "计算器",
+ "todoApp": "Todo应用",
+ "tryPlayground": "我也试试,进入 Playground",
+ "replayControls": "回放控制",
+ "pause": "暂停",
+ "resume": "继续",
+ "preparing": "准备播放中",
+ "replay": "重播",
+ "play": "播放",
+ "prompt": {
+ "element": "生成一个计算器,不要用button,使用div,马卡龙配色,不要使用TinyLayout,要好看的",
+ "page": "创建一个待办应用,界面要丰富,把想到的功能尽量加进去",
+ "elementBubble": "生成一个计算器,使用div,马卡龙配色,要好看的",
+ "pageBubble": "创建一个待办应用,界面要丰富,把想到的功能尽量加进去"
+ }
+ },
+ "guide": {
+ "title": "快速集成生成式UI",
+ "subtitle": "提供强大的渲染组件和开箱即用的对话组件",
+ "devDoc": "开发文档",
+ "step1": {
+ "title": "步骤1:引入并使用chat组件",
+ "description": "开箱即用的chat组件内置了对话界面与消息管理",
+ "mobile": "引入组件"
+ },
+ "step2": {
+ "title": "步骤2:使用chat组件",
+ "description": "简单地配置配套的大模型服务地址,即可体验生成式UI",
+ "mobile": "使用chat组件"
+ },
+ "step3": {
+ "title": "步骤3:添加自定义配置",
+ "description": "强大的定制能力,可定制主题、组件、消息底部工具栏等",
+ "mobile": "自定义配置"
+ }
+ },
+ "feature": {
+ "title": "为开发者而生",
+ "subtitle": "OpenTiny生成式UI具备丰富的特性以及强大生态兼容性",
+ "compatible": {
+ "title": "现有AI生态的兼容",
+ "description": "OpenAI格式兼容,支持MCP服务接入"
+ },
+ "theme": {
+ "title": "定制主题",
+ "description": "支持主题切换、护眼暗黑模式及用户自定义,适配不同使用需求"
+ },
+ "component": {
+ "title": "支持自定义组件",
+ "description": "支持传入自定义组件和组件描述,增强生成式UI能力,丰富生成界面"
+ },
+ "action": {
+ "title": "自定义交互",
+ "description": "支持自定义交互行为,例如跳转新网页、下载附件等灵活操作"
+ },
+ "stack": {
+ "title": "多技术栈支持",
+ "description": "兼容Vue与Angular渲染器,同时支持自定义技术栈渲染扩展"
+ },
+ "more": {
+ "title": "更多功能",
+ "description": "自定义示例和自定义片段,能够助力构建更加优秀的UI界面,满足多样视觉偏好"
+ }
+ },
+ "link": {
+ "title": "即刻体验OpenTiny生成式UI",
+ "description": "增强大模型对话显示与交互,打造极致顺滑的智能体验",
+ "descriptionLine1": "增强大模型对话显示与交互",
+ "descriptionLine2": "打造极致顺滑的智能体验",
+ "tryNow": "立即体验",
+ "productDoc": "产品文档"
+ }
+}
diff --git a/sites/homepage/web/src/static/todo.en.json b/sites/homepage/web/src/static/todo.en.json
new file mode 100644
index 00000000..dd6c6d1f
--- /dev/null
+++ b/sites/homepage/web/src/static/todo.en.json
@@ -0,0 +1,652 @@
+{
+ "componentName": "Page",
+ "state": {
+ "todoList": [
+ {
+ "id": "1",
+ "title": "Complete project requirements document",
+ "description": "Organize product requirements and complete the PRD draft; align with PM and engineering",
+ "priority": "high",
+ "completed": false,
+ "deadline": "2024-12-31",
+ "category": "work"
+ },
+ {
+ "id": "2",
+ "title": "Workout",
+ "description": "30 minutes of cardio and strength training, including 20 minutes on the treadmill and weight training",
+ "priority": "medium",
+ "completed": true,
+ "deadline": "2024-12-10",
+ "category": "life"
+ },
+ {
+ "id": "3",
+ "title": "Buy groceries",
+ "description": "Buy milk, bread, fruit, vegetables, and other daily essentials at the supermarket",
+ "priority": "low",
+ "completed": false,
+ "deadline": "2024-12-08",
+ "category": "life"
+ },
+ {
+ "id": "4",
+ "title": "Learn new React features",
+ "description": "Learn React Server Components and new Hook APIs; complete hands-on practice projects",
+ "priority": "high",
+ "completed": false,
+ "deadline": "2024-12-15",
+ "category": "study"
+ }
+ ],
+ "newTodo": {
+ "title": "",
+ "description": "",
+ "priority": "medium",
+ "deadline": "",
+ "category": "work"
+ },
+ "filterStatus": "all",
+ "filterPriority": "all",
+ "filterCategory": "all",
+ "searchText": ""
+ },
+ "methods": {
+ "addTodo": {
+ "type": "JSFunction",
+ "value": "function() { if (!this.state.newTodo.title.trim()) { return; } const newId = Date.now().toString(); const todo = { ...this.state.newTodo, id: newId, completed: false }; this.state.todoList.push(todo); this.state.newTodo.title = ''; this.state.newTodo.description = ''; this.state.newTodo.priority = 'medium'; this.state.newTodo.deadline = ''; this.state.newTodo.category = 'work'; }"
+ },
+ "toggleTodo": {
+ "type": "JSFunction",
+ "value": "function(id) { const todo = this.state.todoList.find(item => item.id === id); if (todo) { todo.completed = !todo.completed; } }"
+ },
+ "deleteTodo": {
+ "type": "JSFunction",
+ "value": "function(id) { const index = this.state.todoList.findIndex(item => item.id === id); if (index !== -1) { this.state.todoList.splice(index, 1); } }"
+ },
+ "filteredTodos": {
+ "type": "JSFunction",
+ "value": "function() { let filtered = this.state.todoList.filter(todo => { if (this.state.filterStatus === 'active' && todo.completed) return false; if (this.state.filterStatus === 'completed' && !todo.completed) return false; if (this.state.filterPriority !== 'all' && todo.priority !== this.state.filterPriority) return false; if (this.state.filterCategory !== 'all' && todo.category !== this.state.filterCategory) return false; if (this.state.searchText && !todo.title.toLowerCase().includes(this.state.searchText.toLowerCase()) && !todo.description.toLowerCase().includes(this.state.searchText.toLowerCase())) return false; return true; }); return filtered; }"
+ }
+ },
+ "children": [
+ {
+ "componentName": "TinyCard",
+ "children": [
+ {
+ "componentName": "h2",
+ "props": {},
+ "children": "📋 My Todos"
+ },
+ {
+ "componentName": "div",
+ "props": {
+ "style": "margin-bottom: 20px;"
+ },
+ "children": [
+ {
+ "componentName": "TinyRow",
+ "children": [
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 4
+ },
+ "children": [
+ {
+ "componentName": "TinySearch",
+ "props": {
+ "placeholder": "Search todos",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.searchText"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 2
+ },
+ "children": [
+ {
+ "componentName": "TinySelect",
+ "props": {
+ "placeholder": "Filter by status",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.filterStatus"
+ },
+ "options": [
+ {
+ "label": "All",
+ "value": "all"
+ },
+ {
+ "label": "Active",
+ "value": "active"
+ },
+ {
+ "label": "Completed",
+ "value": "completed"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 3
+ },
+ "children": [
+ {
+ "componentName": "TinySelect",
+ "props": {
+ "placeholder": "Priority",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.filterPriority"
+ },
+ "options": [
+ {
+ "label": "All",
+ "value": "all"
+ },
+ {
+ "label": "High",
+ "value": "high"
+ },
+ {
+ "label": "Medium",
+ "value": "medium"
+ },
+ {
+ "label": "Low",
+ "value": "low"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 2
+ },
+ "children": [
+ {
+ "componentName": "TinySelect",
+ "props": {
+ "placeholder": "Category",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.filterCategory"
+ },
+ "options": [
+ {
+ "label": "All",
+ "value": "all"
+ },
+ {
+ "label": "Work",
+ "value": "work"
+ },
+ {
+ "label": "Life",
+ "value": "life"
+ },
+ {
+ "label": "Study",
+ "value": "study"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TinyGrid",
+ "props": {
+ "columns": [
+ {
+ "type": "index",
+ "width": 60,
+ "title": "#"
+ },
+ {
+ "field": "completed",
+ "title": "Status",
+ "width": 80,
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "div",
+ "children": [
+ {
+ "componentName": "TinySwitch",
+ "props": {
+ "modelValue": {
+ "type": "JSExpression",
+ "value": "row.completed"
+ },
+ "onChange": {
+ "type": "JSExpression",
+ "value": "() => this.toggleTodo(row.id)"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ },
+ {
+ "field": "title",
+ "title": "Title",
+ "width": 200,
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "div",
+ "props": {
+ "style": {
+ "type": "JSExpression",
+ "value": "row.completed ? 'text-decoration: line-through; color: #999;' : 'font-weight: bold;'"
+ }
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.title"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ },
+ {
+ "field": "description",
+ "title": "Description",
+ "minWidth": "300px",
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.description"
+ },
+ "style": {
+ "type": "JSExpression",
+ "value": "row.completed ? 'color: #999;' : ''"
+ }
+ }
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ },
+ {
+ "field": "priority",
+ "title": "Priority",
+ "width": 100,
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "div",
+ "props": {
+ "style": {
+ "type": "JSExpression",
+ "value": "row.priority === 'high' ? 'color: #ff4d4f' : row.priority === 'medium' ? 'color: #faad14' : 'color: #52c41a'"
+ }
+ },
+ "children": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "{ high: 'High', medium: 'Medium', low: 'Low' }[row.priority]"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ },
+ {
+ "field": "deadline",
+ "title": "Deadline",
+ "width": 120,
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "row.deadline || 'None'"
+ }
+ }
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ },
+ {
+ "field": "category",
+ "title": "Category",
+ "width": 120,
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "Text",
+ "props": {
+ "text": {
+ "type": "JSExpression",
+ "value": "{ work: 'Work', life: 'Life', study: 'Study' }[row.category] || row.category"
+ }
+ }
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ },
+ {
+ "title": "Actions",
+ "width": 100,
+ "slots": {
+ "default": {
+ "type": "JSSlot",
+ "value": [
+ {
+ "componentName": "TinyButton",
+ "props": {
+ "text": "Delete",
+ "type": "danger",
+ "size": "small",
+ "onClick": {
+ "type": "JSExpression",
+ "value": "() => this.deleteTodo(row.id)"
+ }
+ }
+ }
+ ],
+ "params": [
+ "row"
+ ]
+ }
+ }
+ }
+ ],
+ "data": {
+ "type": "JSExpression",
+ "value": "this.filteredTodos()"
+ }
+ }
+ },
+ {
+ "componentName": "h3",
+ "props": {
+ "style": "margin-top: 30px; margin-bottom: 20px;"
+ },
+ "children": "➕ Add New Todo"
+ },
+ {
+ "componentName": "TinyForm",
+ "props": {
+ "model": {
+ "type": "JSExpression",
+ "value": "this.state.newTodo"
+ },
+ "labelPosition": "top"
+ },
+ "children": [
+ {
+ "componentName": "TinyRow",
+ "children": [
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 6
+ },
+ "children": [
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "Title",
+ "required": true
+ },
+ "children": [
+ {
+ "componentName": "TinyInput",
+ "props": {
+ "placeholder": "Enter todo title",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.newTodo.title"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 6
+ },
+ "children": [
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "Priority"
+ },
+ "children": [
+ {
+ "componentName": "TinySelect",
+ "props": {
+ "placeholder": "Select priority",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.newTodo.priority"
+ },
+ "options": [
+ {
+ "label": "High",
+ "value": "high"
+ },
+ {
+ "label": "Medium",
+ "value": "medium"
+ },
+ {
+ "label": "Low",
+ "value": "low"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TinyRow",
+ "children": [
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 6
+ },
+ "children": [
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "Category"
+ },
+ "children": [
+ {
+ "componentName": "TinySelect",
+ "props": {
+ "placeholder": "Select category",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.newTodo.category"
+ },
+ "options": [
+ {
+ "label": "Work",
+ "value": "work"
+ },
+ {
+ "label": "Life",
+ "value": "life"
+ },
+ {
+ "label": "Study",
+ "value": "study"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TinyCol",
+ "props": {
+ "span": 6
+ },
+ "children": [
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "Deadline"
+ },
+ "children": [
+ {
+ "componentName": "TinyDatePicker",
+ "props": {
+ "placeholder": "Select deadline",
+ "format": "yyyy/MM/dd",
+ "value-format": "yyyy-MM-dd",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.newTodo.deadline"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": "Description"
+ },
+ "children": [
+ {
+ "componentName": "TinyInput",
+ "props": {
+ "type": "textarea",
+ "rows": 3,
+ "placeholder": "Enter detailed description",
+ "modelValue": {
+ "type": "JSExpression",
+ "model": true,
+ "value": "this.state.newTodo.description"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "componentName": "TinyFormItem",
+ "props": {
+ "label": ""
+ },
+ "children": [
+ {
+ "componentName": "TinyButton",
+ "props": {
+ "text": "Add Todo",
+ "type": "primary",
+ "onClick": {
+ "type": "JSExpression",
+ "value": "this.addTodo"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sites/homepage/web/src/views/home.vue b/sites/homepage/web/src/views/home.vue
index 1a0e4d77..8e419c89 100644
--- a/sites/homepage/web/src/views/home.vue
+++ b/sites/homepage/web/src/views/home.vue
@@ -16,6 +16,7 @@ import HomeFeature from '@/components/HomeFeature.vue';
import HomeLink from '@/components/HomeLink.vue';
import HomeExtend from '@/components/HomeExtend.vue';
import HomeMcpToolMobile from '@/components/HomeMcpToolMobile.vue';
+import { t } from '@/i18n';
const abilityContentWrapClass = ref('home-ability-content-wrap');
const abilityThreePartContent = ref({
@@ -59,18 +60,18 @@ const buttonSize = computed(() => {
-
OpenTiny GenUI SDK
-
增强大模型对话展示和交互
-
为用户打造极致顺滑的智能体验,给开发者提供强大的定制能力与生态兼容性
+
{{ t('hero.title') }}
+
{{ t('hero.subtitle') }}
+
{{ t('hero.description') }}
@@ -80,18 +81,14 @@ const buttonSize = computed(() => {
-
+
-
+
{
@@ -119,7 +116,7 @@ const buttonSize = computed(() => {
abilityThreePartContent.subtitle
}}
- Parameters
+ {{ t('ability.mcp.parameters') }}
{
-
+
{
}
&-right {
- width: 60%;
+ width: 55%;
animation: slideUpFromBottom 1.5s cubic-bezier(0.16, 1, 0.3, 1) 0.25s forwards;
opacity: 0;
@@ -234,7 +227,6 @@ const buttonSize = computed(() => {
&-title {
font-size: var(--font-size-title-xl);
- line-height: var(--line-height-title-xl);
font-weight: 700;
text-align: left;
margin-bottom: 6px;
@@ -245,12 +237,10 @@ const buttonSize = computed(() => {
&-subtitle {
font-size: var(--font-size-title-lg);
- line-height: var(--line-height-title-lg);
font-weight: 700;
text-align: left;
color: rgba(14, 112, 255, 1);
margin-bottom: 26px;
- white-space: nowrap;
animation: slideUpFromBottom 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.28s forwards;
opacity: 0;
-webkit-background-clip: text;
@@ -296,7 +286,8 @@ const buttonSize = computed(() => {
}
&-right {
- width: 70%;
+ width: 45%;
+ flex-shrink: 0;
}
}
diff --git a/sites/playground/schema-renderer-ng-adpater/package.json b/sites/playground/schema-renderer-ng-adpater/package.json
index 6b2bee75..b0156e99 100644
--- a/sites/playground/schema-renderer-ng-adpater/package.json
+++ b/sites/playground/schema-renderer-ng-adpater/package.json
@@ -9,10 +9,11 @@
"dist"
],
"scripts": {
+ "prebuild": "pnpm --filter @opentiny/genui-sdk-angular build:element",
"build": "vite build"
},
"dependencies": {
- "@opentiny/tiny-schema-renderer-ng": "workspace:*",
+ "@opentiny/genui-sdk-angular": "workspace:*",
"vue": "^3.5.26"
},
"devDependencies": {
diff --git a/sites/playground/schema-renderer-ng-adpater/src/SchemaRendererNgAdapter.vue b/sites/playground/schema-renderer-ng-adpater/src/SchemaRendererNgAdapter.vue
index fe6826b2..853f88c5 100644
--- a/sites/playground/schema-renderer-ng-adpater/src/SchemaRendererNgAdapter.vue
+++ b/sites/playground/schema-renderer-ng-adpater/src/SchemaRendererNgAdapter.vue
@@ -1,54 +1,20 @@
-
+
-
diff --git a/sites/playground/schema-renderer-ng-adpater/vite.config.ts b/sites/playground/schema-renderer-ng-adpater/vite.config.ts
index e2706f9f..ed03913c 100644
--- a/sites/playground/schema-renderer-ng-adpater/vite.config.ts
+++ b/sites/playground/schema-renderer-ng-adpater/vite.config.ts
@@ -22,7 +22,7 @@ export default defineConfig({
vue({
template: {
compilerOptions: {
- isCustomElement: (tag) => tag === 'tiny-schema-renderer-element-ng',
+ isCustomElement: (tag) => tag === 'genui-renderer-ng-element',
},
},
}),
diff --git a/sites/playground/server/.env.example b/sites/playground/server/.env.example
index d7abd164..c0c71a37 100644
--- a/sites/playground/server/.env.example
+++ b/sites/playground/server/.env.example
@@ -1,4 +1,5 @@
PORT=3008
+
DEEPSEEK_API_KEY=
DEEPSEEK_BASE_URL=https://api.modelarts-maas.com/v1/
# 动态模型地址:配置后从该 URL 拉取模型列表
@@ -9,3 +10,13 @@ DYNAMIC_BASE_URL=
DYNAMIC_API_KEY=
# 本地模型文件路径:配置后会合并到动态模型列表后面
providerModelsPath=maas-models.json
+# OpenAPI API 请求超时(毫秒,默认 60000)
+OPENAPI_API_TIMEOUT_MS=60000
+# OpenAPI 输入安全(默认仅允许内联 JSON/YAML,防 SSRF / 任意文件读)
+# OPENAPI_ALLOW_INLINE=true
+# 本地开发:支持 OpenAPI URL / localhost(生产环境勿开启)
+OPENAPI_ALLOW_URL_FETCH=false
+OPENAPI_ALLOW_LOCALHOST_URL=false
+# OPENAPI_ALLOW_FILE_READ=false
+# OPENAPI_URL_HOST_ALLOWLIST=api.example.com,cdn.example.com
+# OPENAPI_ALLOWED_FILE_DIRS=/absolute/path/to/openapi-specs
diff --git a/sites/playground/server/index.ts b/sites/playground/server/index.ts
index 776e169b..91ccd9ff 100644
--- a/sites/playground/server/index.ts
+++ b/sites/playground/server/index.ts
@@ -7,7 +7,8 @@ import minimist from 'minimist';
import { useProviderModelMapperSync, initProviderModelMapperFromData } from './src/use-provider-mapper.js';
import { loadProviderModelsDataFromFile, mergeProviderModelsData } from './src/provider-models-mapper.js';
import { fetchOpenTinyProviderModelsData } from './src/opentiny-models.js';
-import { createChatGenui, checkMcpHandler } from './src/chat-genui.js';
+import { createChatGenui, checkOpenApiToolsHandler, checkMcpHandler } from './src/chat-genui.js';
+import { fetchAgentCardHandler } from './src/a2a-tools/index.js';
import { createChatTemplate } from './src/chat-template.js';
const __filename = fileURLToPath(import.meta.url);
@@ -19,6 +20,7 @@ const envFileName = mode ? `.env.${mode}` : '.env';
const envPath = path.resolve(__dirname, envFileName);
dotenv.config({ path: envPath });
dotenv.config();
+
const { chatGenuiHandler } = createChatGenui();
const { chatTemplateHandler } = createChatTemplate();
@@ -100,9 +102,11 @@ const getModelsHandler = async (req: Request, res: Response) => {
app.get('/get-models', getModelsHandler);
app.post('/chat-genui', chatGenuiHandler);
app.post('/check-mcp', checkMcpHandler);
+app.post('/check-openapi-tools', checkOpenApiToolsHandler);
+app.post('/fetch-agent-card', fetchAgentCardHandler);
app.post('/chat-template', chatTemplateHandler);
-const port = process.env.PORT || 3008;
+const port = process.env.PORT || 3008
// 启动时先做一次刷新,避免在首次请求前 mapper 为空
updateProviderModels().finally(() => {
diff --git a/sites/playground/server/maas-models.json b/sites/playground/server/maas-models.json
index 6077b579..6952b008 100644
--- a/sites/playground/server/maas-models.json
+++ b/sites/playground/server/maas-models.json
@@ -10,6 +10,23 @@
"supportJsonFormat": false,
"specificPrompt": "schemaJson必须使用```schemaJson```包裹。"
},
+ {
+ "name": "OpenPangu-2.0-Flash",
+ "id": "openpangu-2.0-flash",
+ "supportJsonFormat": false,
+ "specificPrompt": "",
+ "extraBody": {
+ "thinking": {
+ "type": "disabled"
+ }
+ }
+ },
+ {
+ "name": "OpenPangu-2.0-Flash-thinking",
+ "id": "openpangu-2.0-flash",
+ "supportJsonFormat": false,
+ "specificPrompt": ""
+ },
{
"name": "DeepSeek-V4-Flash",
"id": "deepseek-v4-flash",
@@ -75,14 +92,64 @@
"id": "longcat-flash-chat",
"supportJsonFormat": false
},
+ {
+ "name": "GLM5.2",
+ "id": "glm-5.2",
+ "supportJsonFormat": false,
+ "extraBody": {
+ "thinking": {
+ "type": "disabled"
+ }
+ }
+ },
+ {
+ "name": "GLM5.2-thinking",
+ "id": "glm-5.2",
+ "supportJsonFormat": false
+ },
+ {
+ "name": "GLM5.1",
+ "id": "glm-5.1",
+ "supportJsonFormat": false,
+ "extraBody": {
+ "thinking": {
+ "type": "disabled"
+ }
+ }
+ },
+ {
+ "name": "GLM5.1-thinking",
+ "id": "glm-5.1",
+ "supportJsonFormat": false
+ },
{
"name": "GLM5",
"id": "glm-5",
+ "supportJsonFormat": false,
+ "extraBody": {
+ "thinking": {
+ "type": "disabled"
+ }
+ }
+ },
+ {
+ "name": "GLM5-thinking",
+ "id": "glm-5",
"supportJsonFormat": false
},
{
- "name": "Kimi-K2(贵)",
- "id": "Kimi-K2",
+ "name": "Kimi-K2.6",
+ "id": "kimi-k2.6",
+ "supportJsonFormat": false,
+ "extraBody": {
+ "thinking": {
+ "type": "disabled"
+ }
+ }
+ },
+ {
+ "name": "Kimi-K2.6-thinking",
+ "id": "kimi-k2.6",
"supportJsonFormat": false
},
{
diff --git a/sites/playground/server/package.json b/sites/playground/server/package.json
index 4f79f097..e5c057f4 100644
--- a/sites/playground/server/package.json
+++ b/sites/playground/server/package.json
@@ -13,6 +13,8 @@
},
"main": "dist/index.js",
"dependencies": {
+ "@a2a-js/sdk": "^0.3.13",
+ "@a2a-js/sdk-v1": "npm:@a2a-js/sdk@^1.0.0-alpha.0",
"@ai-sdk/anthropic": "^2.0.5",
"@ai-sdk/deepseek": "1.0.7",
"@ai-sdk/openai": "^2.0.10",
@@ -20,25 +22,28 @@
"@openrouter/ai-sdk-provider": "^1.1.2",
"@opentiny/genui-sdk-chat-completions": "workspace:*",
"@opentiny/genui-sdk-core": "workspace:*",
- "@opentiny/genui-sdk-materials-vue-opentiny-vue": "workspace:*",
"@opentiny/genui-sdk-materials-angular-opentiny-ng": "workspace:*",
+ "@opentiny/genui-sdk-materials-vue-opentiny-vue": "workspace:*",
"ai": "5.0.10",
"cors": "^2.8.5",
"dotenv": "^16.5.0",
"express": "^5.1.0",
"express-ws": "^5.0.2",
- "extensionless": "^1.9.9",
+ "@apidevtools/swagger-parser": "^12.1.0",
+ "js-yaml": "^4.1.1",
+ "openapi-types": "^12.1.3",
"json-schema-to-zod": "^2.6.1",
"minimist": "^1.2.8",
"raw-body": "^3.0.0",
- "vite-commit-hash-plugin": "workspace:*",
"uuid": "^11.1.0",
+ "vite-commit-hash-plugin": "workspace:*",
"ws": "^8.18.1",
"zod": "^3.25.76",
"zod-to-json-schema": "^3.25.1"
},
"devDependencies": {
"@types/express": "^5.0.1",
+ "@types/js-yaml": "^4.0.9",
"@types/express-ws": "^3.0.5",
"@types/ws": "^8.18.1",
"tsx": "^4.18.0",
diff --git a/sites/playground/server/src/a2a-tools/agent-tools.ts b/sites/playground/server/src/a2a-tools/agent-tools.ts
deleted file mode 100644
index dabf1004..00000000
--- a/sites/playground/server/src/a2a-tools/agent-tools.ts
+++ /dev/null
@@ -1,202 +0,0 @@
-import { tool } from 'ai';
-import net from 'node:net';
-import { z } from 'zod';
-
-export type PlaygroundAgentConfig = {
- // 前端 IAgentConfig 字段(从 playground.metadata 直接透传)
- name: string;
- agentCardUrl: string;
- description?: string;
- enabled?: boolean;
-
- // Agent Card 解析后在服务端扩展的字段(可选)
- version?: string;
- api?: {
- type?: string;
- url?: string;
- version?: string;
- };
- auth?: {
- type?: string;
- instructions?: string;
- };
- capabilities?: string[];
-};
-
-/** 为 Agent 生成稳定的 ASCII tool 名称,只包含 [a-zA-Z0-9_-]。 */
-const slugifyAgentName = (name: string, index: number): string => {
- const base = (name || '')
- .trim()
- // 替换非 ASCII 字符为下划线
- .replace(/[^a-zA-Z0-9_-]+/g, '_')
- // 去掉头尾的下划线
- .replace(/^_+|_+$/g, '') || 'agent';
-
- // 加上索引,避免不同 Agent 之间因为名称相同导致冲突
- return `agent_${base}_${index}`;
-};
-
-/** 判断 host 是否为本地/内网地址(只做显式阻断,非完整 RFC 覆盖)。 */
-const isPrivateOrLocalHost = (host: string): boolean => {
- const lower = host.toLowerCase();
-
- if (lower === 'localhost' || lower === '127.0.0.1' || lower === '::1') {
- return true;
- }
-
- const ipVersion = net.isIP(host);
- if (!ipVersion) {
- return false;
- }
-
- // 仅处理常见的 IPv4 内网网段
- if (ipVersion === 4) {
- const [a, b] = host.split('.').map((v) => Number(v));
-
- if (a === 10) return true;
- if (a === 172 && b >= 16 && b <= 31) return true;
- if (a === 192 && b === 168) return true;
- if (a === 169 && b === 254) return true; // 链路本地
- }
-
- // 简单拦截常见的 IPv6 私有地址前缀
- if (ipVersion === 6) {
- if (lower.startsWith('fc') || lower.startsWith('fd')) return true;
- }
-
- return false;
-};
-
-/** 校验 Agent 的 api.url,仅允许公网 http/https 目标。 */
-export const isAllowedAgentUrl = (urlStr: string): boolean => {
- try {
- const u = new URL(urlStr);
-
- if (u.protocol !== 'http:' && u.protocol !== 'https:') {
- return false;
- }
-
- if (isPrivateOrLocalHost(u.hostname)) {
- return false;
- }
-
- return true;
- } catch {
- return false;
- }
-};
-
-export const buildAgentTools = (
- agents: PlaygroundAgentConfig[] | undefined,
- abortSignal?: AbortSignal,
-): Record => {
- const agentTools: Record