From 24b24557394b238032dc6b544608d1749a411a3b Mon Sep 17 00:00:00 2001 From: sanmaopep Date: Tue, 28 Oct 2025 14:43:52 +0800 Subject: [PATCH 1/5] docs(materials): fix ref value change docs --- .../docs/src/en/materials/effects/listen-ref-value-change.mdx | 4 ++-- .../docs/src/zh/materials/effects/listen-ref-value-change.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/docs/src/en/materials/effects/listen-ref-value-change.mdx b/apps/docs/src/en/materials/effects/listen-ref-value-change.mdx index 27e2c4177..e4222e486 100644 --- a/apps/docs/src/en/materials/effects/listen-ref-value-change.mdx +++ b/apps/docs/src/en/materials/effects/listen-ref-value-change.mdx @@ -1,6 +1,6 @@ # listenRefValueChange -Listen for changes in the value of the referenced variable and trigger a callback function when it changes. +Listen for changes for the referenced **variable definition** and trigger a callback function when it changes. ## Case Demo @@ -114,4 +114,4 @@ listen-ref-value-change/ #### @flowgram.ai/variable-core -- `getNodeScope(context.node).available.trackByKeyPath`: Tracks changes to the value of the specified path and triggers a callback when the value corresponding to the path changes. \ No newline at end of file +- `getNodeScope(context.node).available.trackByKeyPath`: Tracks changes to the value of the specified path and triggers a callback when the value corresponding to the path changes. diff --git a/apps/docs/src/zh/materials/effects/listen-ref-value-change.mdx b/apps/docs/src/zh/materials/effects/listen-ref-value-change.mdx index c4e8d7ad7..7294c51a7 100644 --- a/apps/docs/src/zh/materials/effects/listen-ref-value-change.mdx +++ b/apps/docs/src/zh/materials/effects/listen-ref-value-change.mdx @@ -1,6 +1,6 @@ # listenRefValueChange -监听引用变量值的变化,并在变化时触发回调函数。 +监听引用**变量定义**的变化,并在变化时触发回调函数。 ## 案例演示 From 1fc081705b2372db3ad766c560c6884622d4fb7a Mon Sep 17 00:00:00 2001 From: sanmaopep Date: Tue, 28 Oct 2025 15:08:10 +0800 Subject: [PATCH 2/5] docs: inject material --- .../en/materials/common/inject-material.mdx | 201 ++++++++++++++++- .../zh/materials/common/inject-material.mdx | 202 +++++++++++++++++- .../src/shared/inject-material/README.md | 170 --------------- .../src/shared/inject-material/README.zh.md | 174 --------------- 4 files changed, 395 insertions(+), 352 deletions(-) delete mode 100644 packages/materials/form-materials/src/shared/inject-material/README.md delete mode 100644 packages/materials/form-materials/src/shared/inject-material/README.zh.md diff --git a/apps/docs/src/en/materials/common/inject-material.mdx b/apps/docs/src/en/materials/common/inject-material.mdx index 5ebe6c524..056cd3907 100644 --- a/apps/docs/src/en/materials/common/inject-material.mdx +++ b/apps/docs/src/en/materials/common/inject-material.mdx @@ -1,11 +1,204 @@ import { SourceCode } from '@theme'; -:::warning -The material has been developed and the documentation is still being improved. Contributions are welcome. +# InjectMaterial + +A **component material** wrapper that supports dependency injection for implementing dynamic component replacement mechanisms. + +:::tip{title="Component Materials Supporting Dependency Injection in the Material Library"} + +- [InjectDynamicValueInput](../components/dynamic-value-input) +- [InjectTypeSelector](../components/type-selector) +- [InjectVariableSelector](../components/variable-selector) + ::: -# Material Dependency Injection (WIP) +## Background: Why Does the Material Library Need Dependency Injection? + +### ❌ Tight Coupling: Traditional Dependency Problems + +```mermaid +graph TD + A[Material A] --> B[Material B] + B --> D[Material D] + C[Material C] --> D + + style D fill:#ff4757 + style A fill:#ffa502 + style B fill:#ffa502 + style C fill:#ffa502 + + note["💥 Problem: Changes to D require modifications to A, B, and C"] +``` + +**Issues:** Chain reactions, high maintenance costs + +### ✅ Decoupling: Dependency Injection Solution + +```mermaid +graph TD + A[Material A] --> RenderKey[Material D RenderKey] + B[Material B] --> RenderKey + C[Material C] --> RenderKey + + RenderKey -.-> BaseD[Default Material D] + CustomD[Custom Material D] -.-> RenderKey + + style RenderKey fill:#3498db + style BaseD fill:#2ed573 + style CustomD fill:#26d0ce + style A fill:#a55eea + style B fill:#a55eea + style C fill:#a55eea + + note2["✅ A, B, C depend on abstract interfaces, decoupled from D's implementation"] +``` + +**Advantages:** Hot-swappable, parallel development, version compatibility + +## Usage + +### Creating Injectable Component Materials + +```tsx +import { createInjectMaterial } from '@flowgram.ai/form-materials'; +import { VariableSelector } from './VariableSelector'; + +// Wrap the component using the createInjectMaterial higher-order component +const InjectVariableSelector = createInjectMaterial(VariableSelector); + +// Now you can use it like a normal component +function MyComponent() { + return ; +} +``` + +### Registering Custom Components + +When a component material is created as an injectable material component and used by other materials, you can inject a custom renderer for that material in `use-editor-props.tsx`: + +```tsx +import { useEditorProps } from '@flowgram.ai/editor'; +import { YourCustomVariableSelector } from './YourCustomVariableSelector'; +import { VariableSelector } from '@flowgram.ai/form-materials'; + +function useCustomEditorProps() { + const editorProps = useEditorProps({ + materials: { + components: { + // By default, the component's Function Name is used as renderKey + 'VariableSelector': YourCustomVariableSelector, + 'TypeSelector': YourCustomTypeSelector, + } + } + }); + + return editorProps; +} +``` + +### Using Custom renderKey + +If your component needs a specific renderKey: + +**Method 1:** Specify renderKey through the second parameter of createInjectMaterial + +```tsx +const InjectCustomComponent = createInjectMaterial(MyComponent, { + renderKey: 'my-custom-key' +}); +// When registering +{ + materials: { + components: { + 'my-custom-key': MyCustomRenderer + } + } +} +``` + +**Method 2:** Or directly set the renderKey property of the component + +```tsx +MyComponent.renderKey = 'my-custom-key'; +const InjectCustomComponent = createInjectMaterial(MyComponent); +// When registering +{ + materials: { + components: { + [MyComponent.renderKey]: MyCustomRenderer + } + } +} + +``` + +:::note{title="Render Key Priority"} + +The determination of component render keys follows this priority order: + +1. `params.renderKey` (second parameter of createInjectMaterial) +2. `Component.renderKey` (renderKey property of the component itself) +3. `Component.name` (display name of the component) +4. Empty string (final fallback) + +::: + +## API Reference + +```typescript +interface CreateInjectMaterialOptions { + renderKey?: string; +} + +function createInjectMaterial( + Component: React.FC & { renderKey?: string }, + params?: CreateInjectMaterialOptions +): React.FC +``` + +## Source Code Guide + +You can copy the source code to your local environment using the CLI command: + +```bash +npx @flowgram.ai/cli@latest materials shared/inject-material +``` + +### Core Sequence Diagram + +Complete component registration and rendering sequence diagram: + +```mermaid +sequenceDiagram + participant App as Application + participant Editor as use-editor-props + participant Registry as FlowRendererRegistry + participant Inject as InjectMaterial + participant Default as Default Component + participant Custom as Custom Component + + Note over App,Custom: Component Registration Phase + App->>Editor: Call use-editor-props() + Editor->>Editor: Configure materials.components + Editor->>Registry: Register component with FlowRendererRegistry + Registry->>Registry: Store mapping relationship + Registry-->>App: Registration complete + + Note over App,Custom: Component Rendering Phase + App->>Inject: Render InjectMaterial component + Inject->>Registry: Query renderer (getRendererComponent) + + alt Custom renderer exists + Registry-->>Inject: Return custom React component + Inject->>Custom: Render using custom component + Custom-->>App: Render custom UI + else No custom renderer + Registry-->>Inject: Return null or type mismatch + Inject->>Default: Render using default component + Default-->>App: Render default UI + end +``` diff --git a/apps/docs/src/zh/materials/common/inject-material.mdx b/apps/docs/src/zh/materials/common/inject-material.mdx index eaf2eec08..beb921bf9 100644 --- a/apps/docs/src/zh/materials/common/inject-material.mdx +++ b/apps/docs/src/zh/materials/common/inject-material.mdx @@ -1,11 +1,205 @@ import { SourceCode } from '@theme'; -:::warning -物料已完成开发,文档还在完善中,欢迎参与贡献 +# InjectMaterial + +一个支持依赖注入的**组件物料**包装器,用于实现动态组件替换机制。 + +:::tip{title="目前物料库中支持依赖注入的组件物料"} + +- [InjectDynamicValueInput](../components/dynamic-value-input) +- [InjectTypeSelector](../components/type-selector) +- [InjectVariableSelector](../components/variable-selector) + +::: + +## 背景:为什么物料库需要依赖注入 ? + +### ❌ 紧耦合:传统依赖问题 + +```mermaid +graph TD + A[物料 A] --> B[物料 B] + B --> D[物料 D] + C[物料 C] --> D + + style D fill:#ff4757 + style A fill:#ffa502 + style B fill:#ffa502 + style C fill:#ffa502 + + note["💥 问题:D变更导致A、B、C全部需要修改"] +``` + +**问题:** 连锁反应、高维护成本 + +### ✅ 解耦:依赖注入方案 + +```mermaid +graph TD + A[物料 A] --> RenderKey[物料 D RenderKey] + B[物料 B] --> RenderKey + C[物料 C] --> RenderKey + + RenderKey -.-> BaseD[默认物料 D] + CustomD[自定义物料 D] -.-> RenderKey + + style RenderKey fill:#3498db + style BaseD fill:#2ed573 + style CustomD fill:#26d0ce + style A fill:#a55eea + style B fill:#a55eea + style C fill:#a55eea + + note2["✅ A、B、C依赖抽象接口,与D实现解耦"] +``` + +**优势:** 热插拔、并行开发、版本兼容 + +## 使用方式 + +### 创建可注入的组件物料 + +```tsx +import { createInjectMaterial } from '@flowgram.ai/form-materials'; +import { VariableSelector } from './VariableSelector'; + +// 使用 createInjectMaterial 高阶组件包装组件 +const InjectVariableSelector = createInjectMaterial(VariableSelector); + +// 现在你可以像使用普通组件一样使用它 +function MyComponent() { + return ; +} +``` + +### 注册自定义组件 + +一个组件物料并创建为可注入的物料组件,当被其他物料使用时候,可以在 `use-editor-props.tsx` 中注入该物料的自定义渲染器: + +```tsx +import { useEditorProps } from '@flowgram.ai/editor'; +import { YourCustomVariableSelector } from './YourCustomVariableSelector'; +import { VariableSelector } from '@flowgram.ai/form-materials'; + +function useCustomEditorProps() { + const editorProps = useEditorProps({ + materials: { + components: { + // 默认使用组件的 Function Name 作为 renderKey + 'VariableSelector': YourCustomVariableSelector, + 'TypeSelector': YourCustomTypeSelector, + } + } + }); + + return editorProps; +} +``` + +### 使用自定义 renderKey + +如果你的组件需要特定的 renderKey: + +**方法 1:** 通过 createInjectMaterial 的第二个参数指定 renderKey + +```tsx +const InjectCustomComponent = createInjectMaterial(MyComponent, { + renderKey: 'my-custom-key' +}); +// 注册时 +{ + materials: { + components: { + 'my-custom-key': MyCustomRenderer + } + } +} +``` + +**方法 2:** 或者直接设置组件的 renderKey 属性 + +```tsx +MyComponent.renderKey = 'my-custom-key'; +const InjectCustomComponent = createInjectMaterial(MyComponent); +// 注册时 +{ + materials: { + components: { + [MyComponent.renderKey]: MyCustomRenderer + } + } +} + +``` + + +:::note{title="渲染键优先级"} + +组件渲染键的确定遵循以下优先级顺序: + +1. `params.renderKey` (createInjectMaterial 的第二个参数) +2. `Component.renderKey` (组件自身的 renderKey 属性) +3. `Component.name` (组件的显示名称) +4. 空字符串 (最终回退) + ::: -# InjectMaterial (WIP) +## API 参考 + +```typescript +interface CreateInjectMaterialOptions { + renderKey?: string; +} + +function createInjectMaterial( + Component: React.FC & { renderKey?: string }, + params?: CreateInjectMaterialOptions +): React.FC +``` + +## 源码导读 + +使用 CLI 命令可以复制源代码到本地: + +```bash +npx @flowgram.ai/cli@latest materials shared/inject-material +``` + +### 核心时序图 + +完整的组件注册和渲染时序图: + +```mermaid +sequenceDiagram + participant App as 应用程序 + participant Editor as use-editor-props + participant Registry as FlowRendererRegistry + participant Inject as InjectMaterial + participant Default as 默认组件 + participant Custom as 自定义组件 + + Note over App,Custom: 组件注册阶段 + App->>Editor: 调用 use-editor-props() + Editor->>Editor: 配置 materials.components + Editor->>Registry: 向 FlowRendererRegistry 注册组件 + Registry->>Registry: 存储映射关系 + Registry-->>App: 注册完成 + + Note over App,Custom: 组件渲染阶段 + App->>Inject: 渲染 InjectMaterial 组件 + Inject->>Registry: 查询渲染器 (getRendererComponent) + + alt 存在自定义渲染器 + Registry-->>Inject: 返回自定义 React 组件 + Inject->>Custom: 使用自定义组件渲染 + Custom-->>App: 渲染自定义 UI + else 无自定义渲染器 + Registry-->>Inject: 返回 null 或类型不匹配 + Inject->>Default: 使用默认组件渲染 + Default-->>App: 渲染默认 UI + end +``` diff --git a/packages/materials/form-materials/src/shared/inject-material/README.md b/packages/materials/form-materials/src/shared/inject-material/README.md deleted file mode 100644 index b07d773d4..000000000 --- a/packages/materials/form-materials/src/shared/inject-material/README.md +++ /dev/null @@ -1,170 +0,0 @@ -# InjectMaterial Component - -A material component wrapper with dependency injection support for implementing dynamic component replacement mechanisms. - -## Why Dependency Injection Matters - -### ❌ Tight Coupling: Traditional Dependency Issues - -```mermaid -graph TD - A[Material A] --> B[Material B] - B --> D[Material D] - C[Material C] --> D - - style D fill:#ff4757 - style A fill:#ffa502 - style B fill:#ffa502 - style C fill:#ffa502 - - note["💥 Problem: D changes require modifications to A, B, C"] -``` - -**Issues:** Chain reactions, high maintenance costs - -### ✅ Decoupling: Dependency Injection Solution - -```mermaid -graph TD - A[Material A] --> RenderKey[Material D RenderKey] - B[Material B] --> RenderKey - C[Material C] --> RenderKey - - RenderKey -.-> BaseD[Origin D] - CustomD[Custom D] -.-> RenderKey - - style RenderKey fill:#5f27cd - style BaseD fill:#2ed573 - style CustomD fill:#26d0ce - style A fill:#a55eea - style B fill:#a55eea - style C fill:#a55eea - - note2["✅ A, B, C depend on abstract interface, decoupled from D"] -``` - -**Benefits:** Hot-swapping, parallel development, version compatibility - -## Features - -- 🔧 **Dependency Injection**: Support dynamic component replacement via FlowRendererRegistry -- 🔄 **Smart Fallback**: Automatically use default component when no custom component is registered -- 🎯 **Type Safety**: Full TypeScript type inference support -- 📦 **Zero Configuration**: Works out of the box without additional setup - -## Usage - -### 1. Create Injectable Material Component - -```tsx -import { createInjectMaterial } from '@flowgram.ai/form-materials'; -import { VariableSelector } from './VariableSelector'; - -// Create injectable material wrapper component -const InjectVariableSelector = createInjectMaterial(VariableSelector); - -// Now you can use it like a regular component -function MyComponent() { - return ; -} -``` - -### 2. Register Custom Components - -Configure custom renderer in `use-editor-props.tsx`: - -```tsx -import { useEditorProps } from '@flowgram.ai/editor'; -import { YourCustomVariableSelector } from './YourCustomVariableSelector'; -import { VariableSelector } from '@flowgram.ai/form-materials'; - -function useCustomEditorProps() { - const editorProps = useEditorProps({ - materials: { - components: { - // Use component's renderKey or component name as key - [VariableSelector.renderKey]: YourCustomVariableSelector, - [TypeSelector.renderKey]: YourCustomTypeSelector, - } - } - }); - - return editorProps; -} -``` - -### 3. Use Custom renderKey - -If your component requires a specific renderKey: - -```tsx -const InjectCustomComponent = createInjectMaterial(MyComponent, { - renderKey: 'my-custom-key' -}); - -// When registering -{ - materials: { - components: { - 'my-custom-key': MyCustomRenderer - } - } -} -``` - -## Sequence Diagram - -Complete component registration and rendering sequence diagram: - -```mermaid -sequenceDiagram - participant App as Application - participant Editor as use-editor-props - participant Registry as FlowRendererRegistry - participant Inject as InjectMaterial - participant Default as Default Component - participant Custom as Custom Component - - Note over App,Custom: Component Registration Phase - App->>Editor: Call use-editor-props() - Editor->>Editor: Configure materials.components - Editor->>Registry: Register component to FlowRendererRegistry - Registry->>Registry: Store mapping relationship - Registry-->>App: Registration complete - - Note over App,Custom: Component Rendering Phase - App->>Inject: Render InjectMaterial component - Inject->>Registry: Query renderer (getRendererComponent) - - alt Custom renderer exists - Registry-->>Inject: Return custom React component - Inject->>Custom: Render with custom component - Custom-->>App: Render custom UI - else No custom renderer - Registry-->>Inject: Return null or type mismatch - Inject->>Default: Render with default component - Default-->>App: Render default UI - end -``` - -## Render Key Priority - -Component render key determination follows this priority order: - -1. `params.renderKey` (second parameter of createInjectMaterial) -2. `Component.renderKey` (component's own renderKey property) -3. `Component.name` (component's display name) -4. Empty string (final fallback) - -## Type Definition - -```typescript -interface CreateInjectMaterialOptions { - renderKey?: string; -} - -function createInjectMaterial( - Component: React.FC & { renderKey?: string }, - params?: CreateInjectMaterialOptions -): React.FC -``` diff --git a/packages/materials/form-materials/src/shared/inject-material/README.zh.md b/packages/materials/form-materials/src/shared/inject-material/README.zh.md deleted file mode 100644 index 65ff5ff9d..000000000 --- a/packages/materials/form-materials/src/shared/inject-material/README.zh.md +++ /dev/null @@ -1,174 +0,0 @@ -# InjectMaterial 组件 - -一个支持依赖注入的 Material 组件包装器,用于实现动态组件替换机制。 - -## 为什么需要依赖注入 - -### ❌ 紧耦合:传统依赖问题 - -```mermaid -graph TD - A[Material A] --> B[Material B] - B --> D[Material D] - C[Material C] --> D - - style D fill:#ff4757 - style A fill:#ffa502 - style B fill:#ffa502 - style C fill:#ffa502 - - note["💥 问题:D变更导致A、B、C全部需要修改"] -``` - -**问题:** 连锁反应、高维护成本 - -### ✅ 解耦:依赖注入方案 - -```mermaid -graph TD - A[Material A] --> RenderKey[Material D RenderKey] - B[Material B] --> RenderKey - C[Material C] --> RenderKey - - RenderKey -.-> BaseD[Origin D] - CustomD[Custom D] -.-> RenderKey - - style RenderKey fill:#5f27cd - style BaseD fill:#2ed573 - style CustomD fill:#26d0ce - style A fill:#a55eea - style B fill:#a55eea - style C fill:#a55eea - - note2["✅ A、B、C依赖抽象接口,与D实现解耦"] -``` - -**优势:** 热插拔、并行开发、版本兼容 - -## 特性 - -- 🔧 **依赖注入**:通过 FlowRendererRegistry 支持动态组件替换 -- 🔄 **智能回退**:当没有注册自定义组件时自动使用默认组件 -- 🎯 **类型安全**:完整的 TypeScript 类型推断支持 -- 📦 **零配置**:开箱即用,无需额外设置 - -## 安装 - -该组件是 `@flowgram.ai/form-materials` 包的一部分,无需单独安装。 - -## 使用 - -### 1. 创建可注入的 Material 组件件 - -```tsx -import { createInjectMaterial } from '@flowgram.ai/form-materials'; -import { VariableSelector } from './VariableSelector'; - -// 创建可注入的Material包装组件 -const InjectVariableSelector = createInjectMaterial(VariableSelector); - -// 现在你可以像使用普通组件一样使用它 -function MyComponent() { - return ; -} -``` - -### 2. 注册自定义组件 - -在 `use-editor-props.tsx` 中配置自定义渲染器: - -```tsx -import { useEditorProps } from '@flowgram.ai/editor'; -import { YourCustomVariableSelector } from './YourCustomVariableSelector'; -import { VariableSelector } from '@flowgram.ai/form-materials'; - -function useCustomEditorProps() { - const editorProps = useEditorProps({ - materials: { - components: { - // 使用组件的 renderKey 或组件名称作为键 - [VariableSelector.renderKey]: YourCustomVariableSelector, - [TypeSelector.renderKey]: YourCustomTypeSelector, - } - } - }); - - return editorProps; -} -``` - -### 3. 使用自定义 renderKey - -如果你的组件需要特定的 renderKey: - -```tsx -const InjectCustomComponent = createInjectMaterial(MyComponent, { - renderKey: 'my-custom-key' -}); - -// 注册时 -{ - materials: { - components: { - 'my-custom-key': MyCustomRenderer - } - } -} -``` - -## 时序图 - -完整的组件注册和渲染时序图: - -```mermaid -sequenceDiagram - participant App as 应用程序 - participant Editor as use-editor-props - participant Registry as FlowRendererRegistry - participant Inject as InjectMaterial - participant Default as 默认组件 - participant Custom as 自定义组件 - - Note over App,Custom: 组件注册阶段 - App->>Editor: 调用 use-editor-props() - Editor->>Editor: 配置 materials.components - Editor->>Registry: 向 FlowRendererRegistry 注册组件 - Registry->>Registry: 存储映射关系 - Registry-->>App: 注册完成 - - Note over App,Custom: 组件渲染阶段 - App->>Inject: 渲染 InjectMaterial 组件 - Inject->>Registry: 查询渲染器 (getRendererComponent) - - alt 存在自定义渲染器 - Registry-->>Inject: 返回自定义 React 组件 - Inject->>Custom: 使用自定义组件渲染 - Custom-->>App: 渲染自定义 UI - else 无自定义渲染器 - Registry-->>Inject: 返回 null 或类型不匹配 - Inject->>Default: 使用默认组件渲染 - Default-->>App: 渲染默认 UI - end -``` - -## 渲染键优先级 - -组件渲染键的确定遵循以下优先级顺序: - -1. `params.renderKey` (createInjectMaterial 的第二个参数) -2. `Component.renderKey` (组件自身的 renderKey 属性) -3. `Component.name` (组件的显示名称) -4. 空字符串 (最终回退) - -## 类型定义 - -```typescript -interface CreateInjectMaterialOptions { - renderKey?: string; -} - -function createInjectMaterial( - Component: React.FC & { renderKey?: string }, - params?: CreateInjectMaterialOptions -): React.FC -``` From 20eb417c7a717b699712a8e07584175c323422d7 Mon Sep 17 00:00:00 2001 From: sanmaopep Date: Tue, 28 Oct 2025 16:01:17 +0800 Subject: [PATCH 3/5] docs: disable declaration plugin --- .../common/disable-declaration-plugin.tsx | 36 ++++++++ .../common/disable-declaration-plugin.mdx | 83 +++++++++++++++++-- .../common/disable-declaration-plugin.mdx | 81 +++++++++++++++++- 3 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 apps/docs/components/form-materials/common/disable-declaration-plugin.tsx diff --git a/apps/docs/components/form-materials/common/disable-declaration-plugin.tsx b/apps/docs/components/form-materials/common/disable-declaration-plugin.tsx new file mode 100644 index 000000000..8b76a848c --- /dev/null +++ b/apps/docs/components/form-materials/common/disable-declaration-plugin.tsx @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates + * SPDX-License-Identifier: MIT + */ + +import React from 'react'; + +import { Field } from '@flowgram.ai/free-layout-editor'; +import { createDisableDeclarationPlugin } from '@flowgram.ai/form-materials'; + +import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder'; + +const VariableSelector = React.lazy(() => + import('@flowgram.ai/form-materials').then((module) => ({ + default: module.VariableSelector, + })) +); + +export const BasicStory = () => ( + [createDisableDeclarationPlugin()]} + formMeta={{ + render: () => ( + <> + + name="variable_selector"> + {({ field }) => ( + field.onChange(value)} /> + )} + + + ), + }} + /> +); diff --git a/apps/docs/src/en/materials/common/disable-declaration-plugin.mdx b/apps/docs/src/en/materials/common/disable-declaration-plugin.mdx index b6bb557a5..1cfaa01b2 100644 --- a/apps/docs/src/en/materials/common/disable-declaration-plugin.mdx +++ b/apps/docs/src/en/materials/common/disable-declaration-plugin.mdx @@ -1,11 +1,84 @@ import { SourceCode } from '@theme'; +import { BasicStory } from 'components/form-materials/common/disable-declaration-plugin'; + +# DisableDeclarationPlugin + +:::note{title=""} + +In the design of the materials library, **"nodes themselves" are defined as VariableDeclaration**. + +Components in the materials library such as [`VariableSelector`](../components/variable-selector), [`PromptEditorWithVariables`](../components/prompt-editor-with-variables), and [`SQLEditorWithVariables`](../components/sql-editor-with-variables) all support selecting **"node"** by default. -:::warning -The material has been developed and the documentation is still being improved. Contributions are welcome. ::: -# DisableDeclarationPlugin (WIP) +DisableDeclarationPlugin can **disable variable declarations (only allowing drilling down)** , making "node" unselectable. + +## Demo + + +### Basic Usage + + + +```tsx pure title="use-editor-props.tsx" +import { createDisableDeclarationPlugin } from '@flowgram.ai/form-materials'; + +// ... +{ + plugins: () => [createDisableDeclarationPlugin()], +} +// ... +``` + +## API + +### createDisableDeclarationPlugin + +Used to create a plugin that disables variable declarations. This plugin intercepts events from the variable engine and marks all variable declarations as disabled. + +```ts +export const createDisableDeclarationPlugin = definePluginCreator({...}); +``` + +**Parameters**: None + +**Return Value**: A plugin instance that can be directly added to the Editor's plugin list. + +## Source Code Guide \ No newline at end of file + href="https://github.com/bytedance/flowgram.ai/blob/main/packages/materials/form-materials/src/plugins/disable-declaration-plugin/create-disable-declaration-plugin.ts" +/> + +You can copy the source code locally using the CLI command: + +```bash +npx @flowgram.ai/cli@latest materials plugins/disable-declaration-plugin +``` + +### Directory Structure + +```plaintext +packages/materials/form-materials/src/plugins/disable-declaration-plugin/ +└── create-disable-declaration-plugin.ts # Main implementation file of the plugin +``` + +### Core Implementation + +The core implementation of DisableDeclarationPlugin is very concise, mainly including the following steps: + +1. **Plugin Initialization**: Create the plugin through `definePluginCreator` and obtain the variable engine instance in the `onInit` hook +2. **Event Listening**: Listen to the `NewAST` and `UpdateAST` events of the variable engine +3. **Processing Logic**: When a variable declaration type (`VariableDeclaration`) AST node is detected, set its `meta.disabled` property to `true` + +This implementation ensures that all newly created or updated variable declarations are automatically disabled, making them unselectable in variable selectors and other components. + +### Dependencies + +#### flowgram API + +[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor) +- [`ASTMatch`](https://flowgram.ai/auto-docs/editor/modules/ASTMatch): A utility class for matching and determining AST node types +- [`definePluginCreator`](https://flowgram.ai/auto-docs/core/functions/definePluginCreator): A function to define plugin creators +- [`GlobalEventActionType`](https://flowgram.ai/auto-docs/editor/interfaces/GlobalEventActionType): Type definitions for global event actions +- [`VariableEngine`](https://flowgram.ai/auto-docs/editor/classes/VariableEngine): Variable engine responsible for managing and processing variable-related operations diff --git a/apps/docs/src/zh/materials/common/disable-declaration-plugin.mdx b/apps/docs/src/zh/materials/common/disable-declaration-plugin.mdx index 6de38b746..9eb395d79 100644 --- a/apps/docs/src/zh/materials/common/disable-declaration-plugin.mdx +++ b/apps/docs/src/zh/materials/common/disable-declaration-plugin.mdx @@ -1,11 +1,84 @@ import { SourceCode } from '@theme'; +import { BasicStory } from 'components/form-materials/common/disable-declaration-plugin'; + +# DisableDeclarationPlugin + +:::note{title=""} + +在物料库的设计中,**“节点本身”作为一种变量声明,是可选的**。 + +物料库中 [`VariableSelector`](../components/variable-selector), [`PromptEditorWithVariables`](../components/prompt-editor-with-variables), [`SQLEditorWithVariables`](../components/sql-editor-with-variables) 等组件,都默认支持选择 **“节点变量”**。 -:::warning -物料已完成开发,文档还在完善中,欢迎参与贡献 ::: -# DisableDeclarationPlugin (WIP) +DisableDeclarationPlugin 可以**禁用变量声明的可选性(只能选下钻)**,从而使“节点变量”不可选。 + +## 案例演示 + + +### 基本使用 + + + +```tsx pure title="use-editor-props.tsx" +import { createDisableDeclarationPlugin } from '@flowgram.ai/form-materials'; + +// ... +{ + plugins: () => [createDisableDeclarationPlugin()], +} +// ... +``` + +## API + +### createDisableDeclarationPlugin + +用于创建禁用变量声明的插件。该插件会拦截变量引擎的事件,将所有变量声明标记为禁用状态。 + +```ts +export const createDisableDeclarationPlugin = definePluginCreator({...}); +``` + +**参数**:无 + +**返回值**:一个插件实例,可直接添加到 Editor 的插件列表中。 + +## 源码导读 + +使用 CLI 命令可以复制源代码到本地: + +```bash +npx @flowgram.ai/cli@latest materials plugins/disable-declaration-plugin +``` + +### 目录结构讲解 + +```plaintext +packages/materials/form-materials/src/plugins/disable-declaration-plugin/ +└── create-disable-declaration-plugin.ts # 插件的主要实现文件 +``` + +### 核心实现说明 + +DisableDeclarationPlugin 的核心实现非常简洁,主要包含以下步骤: + +1. **初始化插件**:通过 `definePluginCreator` 创建插件,并在 `onInit` 钩子中获取变量引擎实例 +2. **事件监听**:监听变量引擎的 `NewAST` 和 `UpdateAST` 事件 +3. **处理逻辑**:当检测到变量声明类型 (`VariableDeclaration`) 的 AST 节点时,将其 `meta.disabled` 属性设置为 `true` + +这种实现方式确保了所有新创建或更新的变量声明都会被自动禁用,从而在变量选择器等组件中不可选。 + +### 依赖梳理 + +#### flowgram API + +[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor) +- [`ASTMatch`](https://flowgram.ai/auto-docs/editor/modules/ASTMatch): 用于匹配和判断 AST 节点类型的工具类 +- [`definePluginCreator`](https://flowgram.ai/auto-docs/core/functions/definePluginCreator): 定义插件创建器的函数 +- [`GlobalEventActionType`](https://flowgram.ai/auto-docs/editor/interfaces/GlobalEventActionType): 全局事件动作的类型定义 +- [`VariableEngine`](https://flowgram.ai/auto-docs/editor/classes/VariableEngine): 变量引擎,负责管理和处理变量相关的操作 From 4271cf80083b606af584b36d84afc4d620ddaa76 Mon Sep 17 00:00:00 2001 From: sanmaopep Date: Tue, 28 Oct 2025 16:56:41 +0800 Subject: [PATCH 4/5] docs: materials quick find --- apps/docs/src/en/materials/introduction.mdx | 57 +++++++++++++++++++++ apps/docs/src/zh/materials/introduction.mdx | 57 +++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/apps/docs/src/en/materials/introduction.mdx b/apps/docs/src/en/materials/introduction.mdx index a3168065f..323232332 100644 --- a/apps/docs/src/en/materials/introduction.mdx +++ b/apps/docs/src/en/materials/introduction.mdx @@ -48,3 +48,60 @@ After the CLI runs successfully, the relevant materials will be automatically ad 3. Some materials depend on other official materials, and the source code of these dependent materials will be added to the project together when the CLI runs ::: + +## Appendix: Finding Materials by Node Type + +### Implementing Node Input and Output + +**Parameter Configuration** +- Node Input: [InputsValues](./components/inputs-values), [InputsValuesTree](./components/inputs-values-tree) +- Node Output: [JsonSchemaEditor](./components/json-schema-editor) +- Input Validation: [validateFlowValue](./validate/validate-flow-value) +- Output Variable Generation: [provideJsonSchemaOutputs](./effects/provide-json-schema-outputs) + +**Parameter Display** +- Input Display: [DisplayInputsValues](./components/display-inputs-values) +- Output Display: [DisplayOutputs](./components/display-outputs) + +### Implementing Code Nodes + +- Code Editor: [CodeEditor](./components/code-editor) + +### Implementing LLM Nodes + +- Prompt Editor: [PromptEditor](./components/prompt-editor) +- Prompt Editor with Variables: [PromptEditorWithVariables](./components/prompt-editor-with-variables) + +### Implementing Condition Branch Nodes + +- Single-line Condition Branch Configuration: [ConditionRow](./components/condition-row) +- Variable Listening for Branch Linkage: [listenRefSchemaChange](./effects/listen-ref-schema-change), [listenRefValueChange](./effects/listen-ref-value-change) + +### Implementing Database Nodes + +- Single-line Database Query Condition Configuration: [DBConditionRow](./components/db-condition-row) +- SQL Editor: [SQLCodeEditor](./components/code-editor) +- SQL Editor with Variables: [SQLEditorWithVariables](./components/sql-editor-with-variables) + + +#### Implementing Loop Nodes + +**Loop Input** +- Loop Input Array Variable Selector: [BatchVariableSelector](./components/batch-variable-selector) +- Item, Index Derivation: [provideBatchInput](./effects/provide-batch-input) + +**Loop Output** +- Loop Output Array Variable Selector: [BatchOutputs](./components/batch-outputs) +- Output Variable Scope Chain Adjustment + Type Derivation: [batchOutputsPlugin](./form-plugins/batch-outputs-plugin) + + +### Implementing HTTP Nodes + +- JSON Editor: [JsonCodeEditor](./components/code-editor) +- JSON Editor with Variables: [JsonEditorWithVariables](./components/json-editor-with-variables) + +### Implementing Variable Assignment/Declaration Nodes + +- Single-line Variable Assignment, Declaration: [AssignRow](./components/assign-row) +- Variable Assignment, Declaration Configuration List: [AssignRows](./components/assign-rows) +- Variable Declaration Type Automatic Derivation: [inferAssignPlugin](./form-plugins/infer-assign-plugin) diff --git a/apps/docs/src/zh/materials/introduction.mdx b/apps/docs/src/zh/materials/introduction.mdx index 0ae74a955..e743b12cf 100644 --- a/apps/docs/src/zh/materials/introduction.mdx +++ b/apps/docs/src/zh/materials/introduction.mdx @@ -48,3 +48,60 @@ CLI 运行成功后,相关物料会自动添加到当前项目下的 `src/form 3. 一些物料会依赖另外一些官方物料,这些被依赖的物料源代码在 CLI 运行时会一起被添加到项目中去 ::: + +## 附:根据节点类型查找物料 + +### 实现节点输入输出 + +**出入参配置** +- 节点入参:[InputsValues](./components/inputs-values), [InputsValuesTree](./components/inputs-values-tree) +- 节点出参:[JsonSchemaEditor](./components/json-schema-editor) +- 入参校验:[validateFlowValue](./validate/validate-flow-value) +- 出参变量生成:[provideJsonSchemaOutputs](./effects/provide-json-schema-outputs) + +**出入参展示** +- 入参展示:[DisplayInputsValues](./components/display-inputs-values) +- 出参展示:[DisplayOutputs](./components/display-outputs) + +### 实现代码节点 + +- 代码编辑器:[CodeEditor](./components/code-editor) + +### 实现大模型节点 + +- 提示词编辑器:[PromptEditor](./components/prompt-editor) +- 可选变量的提示词编辑器:[PromptEditorWithVariables](./components/prompt-editor-with-variables) + +### 实现条件分支节点 + +- 单行条件分支配置:[ConditionRow](./components/condition-row) +- 监听变量实现分支联动:[listenRefSchemaChange](./effects/listen-ref-schema-change), [listenRefValueChange](./effects/listen-ref-value-change) + +### 实现数据库节点 + +- 单行数据库查询条件配置:[DBConditionRow](./components/db-condition-row) +- SQL 编辑器:[SQLCodeEditor](./components/code-editor) +- 可选变量的 SQL 编辑器:[SQLEditorWithVariables](./components/sql-editor-with-variables) + + +#### 实现循环节点 + +**循环输入** +- 循环输入数组变量选择器:[BatchVariableSelector](./components/batch-variable-selector) +- Item、Index 推导:[provideBatchInput](./effects/provide-batch-input) + +**循环输出** +- 循环输出数组变量选择器:[BatchOutputs](./components/batch-outputs) +- 输出变量作用域链调整 + 类型推导:[batchOutputsPlugin](./form-plugins/batch-outputs-plugin) + + +### 实现 HTTP 节点 + +- JSON 编辑器:[JsonCodeEditor](./components/code-editor) +- 可选变量的 JSON 编辑器:[JsonEditorWithVariables](./components/json-editor-with-variables) + +### 实现变量赋值/声明节点 + +- 单行变量赋值、声明:[AssignRow](./components/assign-row) +- 变量赋值、声明配置列表:[AssignRows](./components/assign-rows) +- 变量声明类型自动推导:[inferAssignPlugin](./form-plugins/infer-assign-plugin) From 718f5e3030dd5bf3a98c03a8aacc854531fe8593 Mon Sep 17 00:00:00 2001 From: sanmaopep Date: Tue, 28 Oct 2025 19:16:06 +0800 Subject: [PATCH 5/5] docs: json schema preset --- .../common/json-schema-preset.css | 10 + .../common/json-schema-preset.tsx | 114 +++++++++ .../components/condition-row.tsx | 18 +- .../src/en/materials/common/flow-value.mdx | 26 +- .../en/materials/common/inject-material.mdx | 4 +- .../materials/common/json-schema-preset.mdx | 232 ++++++++++++++++- .../src/zh/materials/common/flow-value.mdx | 26 +- .../zh/materials/common/inject-material.mdx | 4 +- .../materials/common/json-schema-preset.mdx | 235 +++++++++++++++++- .../zh/materials/components/type-selector.mdx | 8 + .../create-type-preset-plugin.tsx | 29 ++- 11 files changed, 650 insertions(+), 56 deletions(-) create mode 100644 apps/docs/components/form-materials/common/json-schema-preset.css create mode 100644 apps/docs/components/form-materials/common/json-schema-preset.tsx diff --git a/apps/docs/components/form-materials/common/json-schema-preset.css b/apps/docs/components/form-materials/common/json-schema-preset.css new file mode 100644 index 000000000..4b9f3cfe3 --- /dev/null +++ b/apps/docs/components/form-materials/common/json-schema-preset.css @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates + * SPDX-License-Identifier: MIT + */ + +.json-schema-color-picker-container { + .semi-colorPicker-popover-defaultChildren { + width: 100%; + } +} diff --git a/apps/docs/components/form-materials/common/json-schema-preset.tsx b/apps/docs/components/form-materials/common/json-schema-preset.tsx new file mode 100644 index 000000000..acf121bc6 --- /dev/null +++ b/apps/docs/components/form-materials/common/json-schema-preset.tsx @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates + * SPDX-License-Identifier: MIT + */ + +import React from 'react'; + +import { Field } from '@flowgram.ai/free-layout-editor'; +import { + ConditionRow, + ConditionRowValueType, + createTypePresetPlugin, + DynamicValueInput, + IFlowConstantRefValue, + type IJsonSchema, +} from '@flowgram.ai/form-materials'; +import { ColorPicker } from '@douyinfe/semi-ui'; +import { IconColorPalette } from '@douyinfe/semi-icons'; + +import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder'; + +import './json-schema-preset.css'; + +const TypeSelector = React.lazy(() => + import('@flowgram.ai/form-materials').then((module) => ({ + default: module.TypeSelector, + })) +); + +export const BasicStory = () => ( + { + node.data.outputs = { + type: 'object', + properties: { + color_output: { + type: 'color', + }, + }, + }; + return node; + }, + }} + plugins={() => [ + createTypePresetPlugin({ + types: [ + { + type: 'color', + icon: , + label: 'Color', + ConstantRenderer: ({ value, onChange }) => ( +
+ onChange?.(_value.hex)} + /> +
+ ), + conditionRule: { + eq: { type: 'color' }, + }, + }, + ], + }), + ]} + formMeta={{ + render: () => ( + <> + + Type Selector: + | undefined> + name="type_selector" + defaultValue={{ type: 'color' }} + > + {({ field }) => ( + field.onChange(value)} /> + )} + +
+ + DynamicValueInput: + + name="dynamic_value_input" + defaultValue={{ type: 'constant', schema: { type: 'color' }, content: '#b5ed0c' }} + > + {({ field }) => ( + field.onChange(value)} /> + )} + +
+ + Condition: + + name="condition_row" + defaultValue={{ + left: { type: 'ref', content: ['start_0', 'color_output'] }, + operator: 'eq', + right: { type: 'ref', content: ['start_0', 'color_output'] }, + }} + > + {({ field }) => ( + field.onChange(value)} /> + )} + +
+ + ), + }} + /> +); diff --git a/apps/docs/components/form-materials/components/condition-row.tsx b/apps/docs/components/form-materials/components/condition-row.tsx index 6e2abfd97..6c94f5fec 100644 --- a/apps/docs/components/form-materials/components/condition-row.tsx +++ b/apps/docs/components/form-materials/components/condition-row.tsx @@ -22,7 +22,23 @@ export const BasicStory = () => ( render: () => ( <> - name="condition_row"> + + name="condition_row" + defaultValue={{ + left: { + type: 'ref', + content: ['start_0', 'str'], + }, + operator: 'eq', + right: { + type: 'constant', + content: 'Hello World!', + schema: { + type: 'string', + }, + }, + }} + > {({ field }) => ( field.onChange(value)} /> )} diff --git a/apps/docs/src/en/materials/common/flow-value.mdx b/apps/docs/src/en/materials/common/flow-value.mdx index fbfa3748b..f2eb7e438 100644 --- a/apps/docs/src/en/materials/common/flow-value.mdx +++ b/apps/docs/src/en/materials/common/flow-value.mdx @@ -1,12 +1,12 @@ import { SourceCode } from '@theme'; -# Flow Value +# FlowValue -Flow Value is a special type used in Flowgram Official Materials to represent data. It can be a constant, reference, expression, or template, providing a flexible way for data transfer and processing in workflows. +FlowValue is a special type used in Flowgram Official Materials to represent data. It can be a constant, reference, expression, or template, providing a flexible way for data transfer and processing in workflows. -## Flow Value Types +## FlowValue Types -Flow Value supports the following four types: +FlowValue supports the following four types: ### 1. Constant A fixed value that does not change at runtime. It can contain any type of data, such as strings, numbers, booleans, or objects. @@ -59,7 +59,7 @@ The expression type is currently in WIP status and does not support type derivat ## FlowValueUtils Utility Class -FlowValueUtils provides rich utility functions for handling Flow Values: +FlowValueUtils provides rich utility functions for handling FlowValues: ### Type Checking Functions @@ -68,17 +68,17 @@ FlowValueUtils provides rich utility functions for handling Flow Values: - `isExpression(value)` - Check if it's an expression type - `isTemplate(value)` - Check if it's a template type - `isConstantOrRef(value)` - Check if it's a constant or reference type -- `isFlowValue(value)` - Check if it's a valid Flow Value type +- `isFlowValue(value)` - Check if it's a valid FlowValue type ### Traversal and Extraction Functions -- `traverse(value, options)` - Traverse all Flow Values in an object, with type filtering support +- `traverse(value, options)` - Traverse all FlowValues in an object, with type filtering support - `getTemplateKeyPaths(templateValue)` - Extract all variable paths from templates ### Schema Inference Functions - `inferConstantJsonSchema(constantValue)` - Infer JSON Schema based on constant value -- `inferJsonSchema(values, scope)` - Infer corresponding JSON Schema based on Flow Value +- `inferJsonSchema(values, scope)` - Infer corresponding JSON Schema based on FlowValue ## Usage Examples @@ -90,7 +90,7 @@ if (FlowValueUtils.isConstant(value)) { console.log('This is a constant value:', value.content); } -// Traverse Flow Values +// Traverse FlowValues for (const { value, path } of FlowValueUtils.traverse(data, { includeTypes: ['ref', 'template'] })) { @@ -108,9 +108,9 @@ console.log('Template variables:', templatePaths); // [['user', 'name'], ['count href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/shared/flow-value/types.ts" /> -The core type definitions of Flow Value include: +The core type definitions of FlowValue include: -- `IFlowValue` - Union type of Flow Value +- `IFlowValue` - Union type of FlowValue - `IFlowConstantValue` - Constant type interface - `IFlowRefValue` - Reference type interface - `IFlowExpressionValue` - Expression type interface @@ -135,7 +135,7 @@ npx @flowgram.ai/cli@latest materials shared/flow-value ``` flow-value/ ├── index.ts # Main entry file, exports all types and utility functions -├── types.ts # Type definitions file, contains all Flow Value interface definitions +├── types.ts # Type definitions file, contains all FlowValue interface definitions ├── schema.ts # Zod schema definitions for runtime type validation ├── utils.ts # Complete implementation of FlowValueUtils utility class └── README.md # Module documentation @@ -143,4 +143,4 @@ flow-value/ ### Third-party APIs Used -- [Zod](https://v3.zod.dev/): Used for type validation and data parsing to determine if Flow Value schemas meet expectations. +- [Zod](https://v3.zod.dev/): Used for type validation and data parsing to determine if FlowValue schemas meet expectations. diff --git a/apps/docs/src/en/materials/common/inject-material.mdx b/apps/docs/src/en/materials/common/inject-material.mdx index 056cd3907..8c723274e 100644 --- a/apps/docs/src/en/materials/common/inject-material.mdx +++ b/apps/docs/src/en/materials/common/inject-material.mdx @@ -1,8 +1,6 @@ import { SourceCode } from '@theme'; -# InjectMaterial - -A **component material** wrapper that supports dependency injection for implementing dynamic component replacement mechanisms. +# Material Dependency Injection :::tip{title="Component Materials Supporting Dependency Injection in the Material Library"} diff --git a/apps/docs/src/en/materials/common/json-schema-preset.mdx b/apps/docs/src/en/materials/common/json-schema-preset.mdx index fddb72fde..2defc0caf 100644 --- a/apps/docs/src/en/materials/common/json-schema-preset.mdx +++ b/apps/docs/src/en/materials/common/json-schema-preset.mdx @@ -1,11 +1,231 @@ import { SourceCode } from '@theme'; +import { BasicStory } from 'components/form-materials/common/json-schema-preset'; -:::warning -The material has been developed and the documentation is still being improved. Contributions are welcome. -::: +# Type Management -# JsonSchemaPreset (WIP) +Type management is implemented in two parts: - + +```tsx pure title="use-editor-props.tsx" +import { createTypePresetPlugin } from "@flowgram.ai/form-materials"; + +// ... +{ + plugins: () => [ + createTypePresetPlugin({ + types: [ + types: [ + { + type: 'color', + icon: , + label: 'Color', + ConstantRenderer: ({ value, onChange }) => ( +
+ onChange?.(_value.hex)} + /> +
+ ), + conditionRule: { + eq: { type: 'color' }, + }, + }, + ], + }, + }), + ], +} +// ... + +``` + +### Getting Type Definitions + +```tsx +const typeManager = useTypeManager(); + +// Get type definition based on schema +const type = typeManager.getTypeBySchema({ type: "color" }); +const type2 = typeManager.getTypeBySchema({ type: "array", items: { type: "color" } }); + +// Get type definition based on type name +const type3 = typeManager.getTypeByName("color"); +``` + +## API + +### createTypePresetPlugin + +Create an Editor Plugin for extending material library preset type definitions or disabling certain preset types in the material library. + +```typescript +function createTypePresetPlugin(options: TypePresetPluginOptions): Plugin; + +interface TypePresetPluginOptions { + // Array of custom type definitions to add + types?: TypePresetRegistry[]; + // Array of type names to remove + unregisterTypes?: string[]; +} + +interface TypePresetRegistry { + // Type name + type: string; + // Type icon + icon?: React.ReactNode; + // Type label + label?: string; + // Constant renderer component + ConstantRenderer: React.FC; + // Condition rule configuration + conditionRule?: IConditionRule | IConditionRuleFactory; + // Other properties inherited from base type +} + +interface ConstantRendererProps { + value?: Value; + onChange?: (value: Value) => void; + readonly?: boolean; + [key: string]: any; +} +``` + +## Source Code Guide + +Material layer source code: \ No newline at end of file +/> + +Use the CLI command to copy the material layer source code to local: + +```bash +npx @flowgram.ai/cli@latest materials plugins/json-schema-preset +``` + +Engine layer source code: + +Due to its complexity, the engine layer currently needs to be used through the separate `@flowgram.ai/json-schema` package, and does not support downloading source code via CLI commands. + +### Material Layer Core Logic + +The definitions added in the material layer are used by the following materials: +- [ConstantInput](../components/constant-input): Get constant input corresponding to the type + - Source code: +- [ConditionContext](../components/condition-context): Get Condition rules corresponding to the type + - Source code: + +### Engine Layer Core Logic + +#### JsonSchemaTypeManager Class Structure + +```mermaid +classDiagram + direction LR + class BaseTypeManager { + -getTypeNameFromSchema(typeSchema): string + +getTypeByName(typeName): Registry + +getTypeBySchema(type): Registry + +getDefaultTypeRegistry(): Registry + +getAllTypeRegistries(): Registry[] + +register(registry): void + +unregister(typeName): void + } + + class JsonSchemaTypeManager { + +constructor() + +getTypeRegistriesWithParentType(parentType): Registry[] + +getTypeSchemaDeepChildField(type): Schema + +getComplexText(type): string + +getDisplayIcon(type): ReactNode + +getTypeSchemaProperties(type): Record + +getPropertiesParent(type): Schema + +getJsonPaths(type): string[] + +canAddField(type): boolean + +getDefaultValue(type): unknown + } + + BaseTypeManager <|-- JsonSchemaTypeManager + + class JsonSchemaTypeRegistry { + +type: string + +label: string + +icon: ReactNode + +container: boolean + +getJsonPaths(typeSchema): string[] + +getDisplayIcon(typeSchema): ReactNode + +getPropertiesParent(typeSchema): Schema + +canAddField(typeSchema): boolean + +getDefaultValue(): unknown + +getValueText(value): string + +getTypeSchemaProperties(typeSchema): Record + +getStringValueByTypeSchema(typeSchema): string + +getTypeSchemaByStringValue(optionValue): Schema + +getDefaultSchema(): Schema + +customComplexText(typeSchema): string + } + <> JsonSchemaTypeRegistry + + JsonSchemaTypeManager --> JsonSchemaTypeRegistry: register +``` + +#### JsonSchemaTypeManager Function Overview + +**Core Functions**: + +1. **Type Registration and Management** + - `register(registry)`: Register new type definitions + - `unregister(typeName)`: Remove registered types + - `getAllTypeRegistries()`: Get all registered types + - `getTypeByName(typeName)`: Get type definition by type name + - `getTypeBySchema(schema)`: Get corresponding type definition by schema + +2. **Type Information Retrieval** + - `getTypeNameFromSchema(schema)`: Extract type name from schema + - `getTypeRegistriesWithParentType(parentType)`: Get all types under specified parent type + - `getTypeSchemaDeepChildField(type)`: Get the deepest child field of a type + - `getComplexText(type)`: Get complex text representation of type (e.g., Array\) + - `getDisplayIcon(type)`: Get display icon of type + +3. **Type Property Operations** + - `getTypeSchemaProperties(type)`: Get property definitions of type + - `getPropertiesParent(type)`: Get parent node of properties + - `getJsonPaths(type)`: Get json paths of type in flow schema + - `canAddField(type)`: Determine if fields can be added to the type + - `getDefaultValue(type)`: Get default value of type + +**Initialization Process**: + +In the constructor, JsonSchemaTypeManager automatically registers a series of default type definitions: +- defaultTypeDefinitionRegistry: Default type definition +- stringRegistryCreator: String type +- integerRegistryCreator: Integer type +- numberRegistryCreator: Number type +- booleanRegistryCreator: Boolean type +- objectRegistryCreator: Object type +- arrayRegistryCreator: Array type +- unknownRegistryCreator: Unknown type +- mapRegistryCreator: Map type +- dateTimeRegistryCreator: DateTime type diff --git a/apps/docs/src/zh/materials/common/flow-value.mdx b/apps/docs/src/zh/materials/common/flow-value.mdx index 3e02f1e78..862d91e64 100644 --- a/apps/docs/src/zh/materials/common/flow-value.mdx +++ b/apps/docs/src/zh/materials/common/flow-value.mdx @@ -1,12 +1,12 @@ import { SourceCode } from '@theme'; -# Flow Value +# FlowValue -Flow Value 是指在 Flowgram 官方物料库 中用于表示数据的一种特殊类型。它可以是常量、引用、表达式或模板,为流程中的数据传递和处理提供了灵活的方式。 +FlowValue 是指在 Flowgram 官方物料库 中用于表示数据的一种特殊类型。它可以是常量、引用、表达式或模板,为流程中的数据传递和处理提供了灵活的方式。 -## Flow Value 类型 +## FlowValue 类型 -Flow Value 支持以下四种类型: +FlowValue 支持以下四种类型: ### 1. 常量 (Constant) 固定值,在运行时不会改变。可以包含任意类型的数据,如字符串、数字、布尔值或对象。 @@ -59,7 +59,7 @@ JavaScript 表达式,在运行时会进行求值计算。 ## FlowValueUtils 工具类 -FlowValueUtils 提供了丰富的工具函数来处理 Flow Value: +FlowValueUtils 提供了丰富的工具函数来处理 FlowValue: ### 类型判断函数 @@ -68,17 +68,17 @@ FlowValueUtils 提供了丰富的工具函数来处理 Flow Value: - `isExpression(value)` - 判断是否为表达式类型 - `isTemplate(value)` - 判断是否为模板类型 - `isConstantOrRef(value)` - 判断是否为常量或引用类型 -- `isFlowValue(value)` - 判断是否为有效的 Flow Value 类型 +- `isFlowValue(value)` - 判断是否为有效的 FlowValue 类型 ### 遍历和提取函数 -- `traverse(value, options)` - 遍历对象中的所有 Flow Value,支持按类型筛选 +- `traverse(value, options)` - 遍历对象中的所有 FlowValue,支持按类型筛选 - `getTemplateKeyPaths(templateValue)` - 提取模板中所有的变量路径 ### Schema 推断函数 - `inferConstantJsonSchema(constantValue)` - 根据常量值推断 JSON Schema -- `inferJsonSchema(values, scope)` - 根据 Flow Value 推断对应的 JSON Schema +- `inferJsonSchema(values, scope)` - 根据 FlowValue 推断对应的 JSON Schema ## 使用示例 @@ -90,7 +90,7 @@ if (FlowValueUtils.isConstant(value)) { console.log('This is a constant value:', value.content); } -// 遍历 Flow Values +// 遍历 FlowValues for (const { value, path } of FlowValueUtils.traverse(data, { includeTypes: ['ref', 'template'] })) { @@ -108,9 +108,9 @@ console.log('Template variables:', templatePaths); // [['user', 'name'], ['count href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/shared/flow-value/types.ts" /> -Flow Value 的核心类型定义包括: +FlowValue 的核心类型定义包括: -- `IFlowValue` - Flow Value 的联合类型 +- `IFlowValue` - FlowValue 的联合类型 - `IFlowConstantValue` - 常量类型接口 - `IFlowRefValue` - 引用类型接口 - `IFlowExpressionValue` - 表达式类型接口 @@ -135,7 +135,7 @@ npx @flowgram.ai/cli@latest materials shared/flow-value ``` flow-value/ ├── index.ts # 主入口文件,导出所有类型和工具函数 -├── types.ts # 类型定义文件,包含所有 Flow Value 接口定义 +├── types.ts # 类型定义文件,包含所有 FlowValue 接口定义 ├── schema.ts # Zod 模式定义,用于运行时类型验证 ├── utils.ts # FlowValueUtils 工具类的完整实现 └── README.md # 模块说明文档 @@ -143,4 +143,4 @@ flow-value/ ### 使用到的第三方 API -- [Zod](https://v3.zod.dev/): 用于类型验证和数据解析,判断 Flow Value 的 Schema 是否符合预期。 +- [Zod](https://v3.zod.dev/): 用于类型验证和数据解析,判断 FlowValue 的 Schema 是否符合预期。 diff --git a/apps/docs/src/zh/materials/common/inject-material.mdx b/apps/docs/src/zh/materials/common/inject-material.mdx index beb921bf9..53b0b0126 100644 --- a/apps/docs/src/zh/materials/common/inject-material.mdx +++ b/apps/docs/src/zh/materials/common/inject-material.mdx @@ -1,8 +1,6 @@ import { SourceCode } from '@theme'; -# InjectMaterial - -一个支持依赖注入的**组件物料**包装器,用于实现动态组件替换机制。 +# 物料组件依赖注入 :::tip{title="目前物料库中支持依赖注入的组件物料"} diff --git a/apps/docs/src/zh/materials/common/json-schema-preset.mdx b/apps/docs/src/zh/materials/common/json-schema-preset.mdx index 8f7232dea..3490e91e1 100644 --- a/apps/docs/src/zh/materials/common/json-schema-preset.mdx +++ b/apps/docs/src/zh/materials/common/json-schema-preset.mdx @@ -1,11 +1,236 @@ import { SourceCode } from '@theme'; +import { BasicStory } from 'components/form-materials/common/json-schema-preset'; -:::warning -物料已完成开发,文档还在完善中,欢迎参与贡献 -::: +# 类型管理 -# JsonSchemaPreset (WIP) +物料库类型管理分为两部分实现: - + + +```tsx pure title="use-editor-props.tsx" +import { createTypePresetPlugin } from "@flowgram.ai/form-materials"; + +// ... +{ + plugins: () => [ + createTypePresetPlugin({ + types: [ + types: [ + { + type: 'color', + icon: , + label: 'Color', + ConstantRenderer: ({ value, onChange }) => ( +
+ onChange?.(_value.hex)} + /> +
+ ), + conditionRule: { + eq: { type: 'color' }, + }, + }, + ], + ], + }), + ], +} +// ... + +``` + + +### 获取类型定义 + + +```tsx +const typeManager = useTypeManager(); + +// 根据 schema 获取类型定义 +const type = typeManager.getTypeBySchema({ type: "color" }); +const type2 = typeManager.getTypeBySchema({ type: "array", items: { type: "color" } }); + +// 根据类型名获取类型定义 +const type3 = typeManager.getTypeByName("color"); +``` + + +## API + +### createTypePresetPlugin + +创建一个 Editor Plugin,用于扩展物料库预设类型定义,或者关闭某些物料库中预设的类型。 + +```typescript +function createTypePresetPlugin(options: TypePresetPluginOptions): Plugin; + +interface TypePresetPluginOptions { + // 要添加的自定义类型定义数组 + types?: TypePresetRegistry[]; + // 要移除的类型名称数组 + unregisterTypes?: string[]; +} + +interface TypePresetRegistry { + // 类型名称 + type: string; + // 类型图标 + icon?: React.ReactNode; + // 类型标签 + label?: string; + // 常量渲染器组件 + ConstantRenderer: React.FC; + // 条件规则配置 + conditionRule?: IConditionRule | IConditionRuleFactory; + // 其他从基础类型继承的属性 +} + +interface ConstantRendererProps { + value?: Value; + onChange?: (value: Value) => void; + readonly?: boolean; + [key: string]: any; +} +``` + +## 源码导读 + +物料层源代码: + +使用 CLI 命令可以复制物料层源代码到本地: + +```bash +npx @flowgram.ai/cli@latest materials plugins/json-schema-preset +``` + +引擎层源代码: + +引擎层由于复杂度较高,因此目前需要通过单独的 `@flowgram.ai/json-schema` 包使用,不支持 CLI 命令下载源代码。 + +### 物料层核心逻辑 + +物料层新增的定义被以下物料使用: +- [ConstantInput](../components/constant-input): 获取类型对应的常量输入 + - 源代码见: +- [ConditionContext](../components/condition-context):获取类型对应的 Condition 规则 + - 源代码见: + +### 引擎层核心逻辑 + +#### JsonSchemaTypeManager 类结构 + +```mermaid +classDiagram + direction LR + class BaseTypeManager { + -getTypeNameFromSchema(typeSchema): string + +getTypeByName(typeName): Registry + +getTypeBySchema(type): Registry + +getDefaultTypeRegistry(): Registry + +getAllTypeRegistries(): Registry[] + +register(registry): void + +unregister(typeName): void + } + + class JsonSchemaTypeManager { + +constructor() + +getTypeRegistriesWithParentType(parentType): Registry[] + +getTypeSchemaDeepChildField(type): Schema + +getComplexText(type): string + +getDisplayIcon(type): ReactNode + +getTypeSchemaProperties(type): Record + +getPropertiesParent(type): Schema + +getJsonPaths(type): string[] + +canAddField(type): boolean + +getDefaultValue(type): unknown + } + + BaseTypeManager <|-- JsonSchemaTypeManager + + class JsonSchemaTypeRegistry { + +type: string + +label: string + +icon: ReactNode + +container: boolean + +getJsonPaths(typeSchema): string[] + +getDisplayIcon(typeSchema): ReactNode + +getPropertiesParent(typeSchema): Schema + +canAddField(typeSchema): boolean + +getDefaultValue(): unknown + +getValueText(value): string + +getTypeSchemaProperties(typeSchema): Record + +getStringValueByTypeSchema(typeSchema): string + +getTypeSchemaByStringValue(optionValue): Schema + +getDefaultSchema(): Schema + +customComplexText(typeSchema): string + } + <> JsonSchemaTypeRegistry + + JsonSchemaTypeManager --> JsonSchemaTypeRegistry: register +``` + +#### JsonSchemaTypeManager 功能概览 + +**核心功能**: + +1. **类型注册与管理** + - `register(registry)`: 注册新的类型定义 + - `unregister(typeName)`: 移除已注册的类型 + - `getAllTypeRegistries()`: 获取所有已注册的类型 + - `getTypeByName(typeName)`: 通过类型名称获取类型定义 + - `getTypeBySchema(schema)`: 通过 schema 获取对应的类型定义 + +2. **类型信息获取** + - `getTypeNameFromSchema(schema)`: 从 schema 中提取类型名称 + - `getTypeRegistriesWithParentType(parentType)`: 获取指定父类型下的所有类型 + - `getTypeSchemaDeepChildField(type)`: 获取类型的最深层子字段 + - `getComplexText(type)`: 获取类型的复杂文本表示(如 Array\) + - `getDisplayIcon(type)`: 获取类型的显示图标 + +3. **类型属性操作** + - `getTypeSchemaProperties(type)`: 获取类型的属性定义 + - `getPropertiesParent(type)`: 获取属性的父节点 + - `getJsonPaths(type)`: 获取类型在 flow schema 中的 json 路径 + - `canAddField(type)`: 判断是否可以向类型添加字段 + - `getDefaultValue(type)`: 获取类型的默认值 + +**初始化过程**: + +在构造函数中,JsonSchemaTypeManager 会自动注册一系列默认类型定义: +- defaultTypeDefinitionRegistry: 默认类型定义 +- stringRegistryCreator: 字符串类型 +- integerRegistryCreator: 整数类型 +- numberRegistryCreator: 数字类型 +- booleanRegistryCreator: 布尔类型 +- objectRegistryCreator: 对象类型 +- arrayRegistryCreator: 数组类型 +- unknownRegistryCreator: 未知类型 +- mapRegistryCreator: 映射类型 +- dateTimeRegistryCreator: 日期时间类型 + diff --git a/apps/docs/src/zh/materials/components/type-selector.mdx b/apps/docs/src/zh/materials/components/type-selector.mdx index 20576a317..58122df43 100644 --- a/apps/docs/src/zh/materials/components/type-selector.mdx +++ b/apps/docs/src/zh/materials/components/type-selector.mdx @@ -10,6 +10,10 @@ TypeSelector 是一个类型选择器组件,用于在表单中选择 JSON Sche TypeSelector 组件 +:::tip +If you want to add new variable types, please read [Type Management](../common/json-schema-preset) +::: + ## 案例演示 ### 基本使用 @@ -33,6 +37,10 @@ const formMeta = { } ``` +### 新增新类型 + +详见: + ## API 参考 diff --git a/packages/materials/form-materials/src/plugins/json-schema-preset/create-type-preset-plugin.tsx b/packages/materials/form-materials/src/plugins/json-schema-preset/create-type-preset-plugin.tsx index c406aca06..594e3dc3b 100644 --- a/packages/materials/form-materials/src/plugins/json-schema-preset/create-type-preset-plugin.tsx +++ b/packages/materials/form-materials/src/plugins/json-schema-preset/create-type-preset-plugin.tsx @@ -8,23 +8,28 @@ import { jsonSchemaContainerModule, JsonSchemaTypeManager, } from '@flowgram.ai/json-schema'; -import { definePluginCreator } from '@flowgram.ai/editor'; +import { definePluginCreator, type PluginCreator } from '@flowgram.ai/editor'; import { JsonSchemaTypeRegistry } from './types'; import { initRegistries, jsonSchemaTypePreset } from './type-definition'; initRegistries(); -export const createTypePresetPlugin = definePluginCreator<{ - types?: Partial & Pick[]; +type TypePresetRegistry = Partial & Pick; + +interface TypePresetPluginOptions { + types?: TypePresetRegistry[]; unregisterTypes?: string[]; -}>({ - onInit(ctx, opts) { - const typeManager = ctx.get(BaseTypeManager) as JsonSchemaTypeManager; - jsonSchemaTypePreset.forEach((_type) => typeManager.register(_type)); +} + +export const createTypePresetPlugin: PluginCreator = + definePluginCreator({ + onInit(ctx, opts) { + const typeManager = ctx.get(BaseTypeManager) as JsonSchemaTypeManager; + jsonSchemaTypePreset.forEach((_type) => typeManager.register(_type)); - opts.types?.forEach((_type) => typeManager.register(_type)); - opts.unregisterTypes?.forEach((_type) => typeManager.unregister(_type)); - }, - containerModules: [jsonSchemaContainerModule], -}); + opts.types?.forEach((_type) => typeManager.register(_type)); + opts.unregisterTypes?.forEach((_type) => typeManager.unregister(_type)); + }, + containerModules: [jsonSchemaContainerModule], + });