Browse Source

docs(materials): add docs for materials (#982)

* docs(material): infer inputs plugin

* feat: init agents md and claude md

* docs(materials): variable node materials

* docs: display outputs

* docs: constant input

* docs: coze editor extensions

* fix: ci

* docs: add material component doc skill and finish batch variable selector

* fix: ci

* chore: remove license in SKILL

* fix: template path in skill
Yiwei Mao 2 months ago
parent
commit
ab14ec2fb1
29 changed files with 3934 additions and 69 deletions
  1. 378 0
      .claude/skills/material-component-doc/SKILL.md
  2. 172 0
      .claude/skills/material-component-doc/templates/material.mdx
  3. 16 0
      AGENTS.md
  4. 233 0
      CLAUDE.md
  5. 71 0
      apps/docs/components/form-materials/components/assign-row.tsx
  6. 28 0
      apps/docs/components/form-materials/components/assign-rows.tsx
  7. 58 0
      apps/docs/components/form-materials/components/batch-variable-selector.tsx
  8. 152 0
      apps/docs/components/form-materials/components/constant-inputs.tsx
  9. 96 0
      apps/docs/components/form-materials/components/display-outputs.tsx
  10. 90 0
      apps/docs/components/form-materials/form-plugins/infer-assign-plugin.tsx
  11. 104 0
      apps/docs/components/form-materials/form-plugins/infer-inputs-plugin.tsx
  12. 156 5
      apps/docs/src/en/materials/components/assign-row.mdx
  13. 105 4
      apps/docs/src/en/materials/components/assign-rows.mdx
  14. 200 3
      apps/docs/src/en/materials/components/batch-variable-selector.mdx
  15. 168 4
      apps/docs/src/en/materials/components/constant-input.mdx
  16. 155 4
      apps/docs/src/en/materials/components/coze-editor-extensions.mdx
  17. 135 5
      apps/docs/src/en/materials/components/display-outputs.mdx
  18. 157 3
      apps/docs/src/en/materials/form-plugins/infer-assign-plugin.mdx
  19. 188 5
      apps/docs/src/en/materials/form-plugins/infer-inputs-plugin.mdx
  20. 157 4
      apps/docs/src/zh/materials/components/assign-row.mdx
  21. 107 3
      apps/docs/src/zh/materials/components/assign-rows.mdx
  22. 200 2
      apps/docs/src/zh/materials/components/batch-variable-selector.mdx
  23. 169 3
      apps/docs/src/zh/materials/components/constant-input.mdx
  24. 155 3
      apps/docs/src/zh/materials/components/coze-editor-extensions.mdx
  25. 125 4
      apps/docs/src/zh/materials/components/display-outputs.mdx
  26. 157 3
      apps/docs/src/zh/materials/form-plugins/infer-assign-plugin.mdx
  27. 190 4
      apps/docs/src/zh/materials/form-plugins/infer-inputs-plugin.mdx
  28. 7 6
      packages/materials/form-materials/src/components/assign-rows/index.tsx
  29. 5 4
      packages/materials/form-materials/src/components/display-outputs/index.tsx

+ 378 - 0
.claude/skills/material-component-doc/SKILL.md

@@ -0,0 +1,378 @@
+---
+name: material-component-doc
+description: 用于 FlowGram 物料库组件文档撰写的专用技能,提供组件文档生成、Story 创建、翻译等功能的指导和自动化支持
+metadata:
+  version: "1.1.0"
+  category: "documentation"
+  language: "zh-CN"
+  framework: "FlowGram"
+---
+
+# FlowGram 文档的组织结构
+
+- **英文文档**: `apps/docs/src/en`
+- **中文文档**: `apps/docs/src/zh`
+- **Story 组件**: `apps/docs/components/form-materials/components`
+- **物料源码**: `packages/materials/form-materials/src/components`
+- **文档模板**: `./templates/material.mdx`
+
+# 组件物料文档撰写流程
+
+## 1. 源码定位
+
+在 `packages/materials/form-materials/src/components` 目录下确认物料源代码地址。
+
+**操作**:
+- 使用 Glob 工具搜索物料文件
+- 确认目录结构(是否有 hooks.ts, context.tsx 等)
+- 记录导出名称和文件路径
+
+## 2. 需求收集
+
+向用户询问物料使用实例和具体需求。
+
+**收集信息**:
+- 主要使用场景
+- 典型代码示例(1-2 个)
+- 特殊配置或高级用法
+- 是否需要配图
+
+## 3. 功能分析
+
+深入阅读源代码,理解物料功能。
+
+**分析要点**:
+- Props 接口(类型、默认值、描述)
+- 核心功能和实现方式
+- 依赖关系(FlowGram API、其他物料、第三方库)
+- Hooks 和 Context
+- 特殊逻辑(条件渲染、副作用等)
+
+## 4. Story 创建
+
+在 `apps/docs/components/form-materials/components` 下创建 Story 组件(详见下方 Story 规范)。
+
+## 5. 文档撰写
+
+基于模板 `./templates/material.mdx` 撰写完整文档。
+
+**文档位置**:
+- 中文:`apps/docs/src/zh/materials/components/{物料名称}.mdx`
+- 英文:`apps/docs/src/en/materials/components/{物料名称}.mdx`(翻译后)
+
+## 6. 质量检查
+
+**检查清单**:
+- [ ] Story 组件能正常运行
+- [ ] 代码示例准确无误
+- [ ] API 表格完整
+- [ ] 依赖链接正确可访问
+- [ ] 图片路径正确
+- [ ] Mermaid 流程图语法正确
+- [ ] CLI 命令路径准确
+
+**用户确认中文文档的撰写后,再执行翻译**。
+**用户确认中文文档的撰写后,再执行翻译**。
+**用户确认中文文档的撰写后,再执行翻译**。
+---
+
+# Story 组件规范
+
+> **参考示例**: `apps/docs/components/form-materials/components/variable-selector.tsx`
+
+## 命名规范
+
+**文件命名**: kebab-case,与物料名称一致
+- ✅ `variable-selector.tsx`
+- ✅ `dynamic-value-input.tsx`
+- ❌ `VariableSelector.tsx`
+
+**Story 导出命名**: PascalCase + "Story" 后缀
+- `BasicStory` - 基础使用(必需)
+- `WithSchemaStory` - 带 Schema 约束
+- `DisabledStory` - 禁用状态
+- `CustomFilterStory` - 自定义过滤
+- 根据物料特性命名,见名知意
+
+## 代码要求
+
+### 1. 懒加载导入
+
+```tsx
+// ✅ 正确
+const VariableSelector = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.VariableSelector,
+  }))
+);
+
+// ❌ 错误
+import { VariableSelector } from '@flowgram.ai/form-materials';
+```
+
+### 2. 包装组件
+
+```tsx
+// ✅ 正确
+export const BasicStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<string[]> name="variable_selector">
+            {({ field }) => (
+              <VariableSelector
+                value={field.value}
+                onChange={(value) => field.onChange(value)}
+              />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);
+
+// ❌ 错误:缺少包装
+export const BasicStory = () => (
+  <VariableSelector value={[]} onChange={() => {}} />
+);
+```
+
+### 3. 类型标注
+
+```tsx
+// ✅ 正确
+<Field<string[] | undefined> name="variable_selector">
+
+// ❌ 错误
+<Field<any> name="variable_selector">
+```
+
+### 4. 语言规范
+
+代码和注释只使用英文,无中文。
+
+## 完整示例
+
+```tsx
+/**
+ * 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 { 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 = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<string[] | undefined> name="variable_selector">
+            {({ field }) => (
+              <VariableSelector
+                value={field.value}
+                onChange={(value) => field.onChange(value)}
+              />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);
+
+export const FilterSchemaStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<string[] | undefined> name="variable_selector">
+            {({ field }) => (
+              <VariableSelector
+                value={field.value}
+                onChange={(value) => field.onChange(value)}
+                includeSchema={{ type: 'string' }}
+              />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);
+```
+
+---
+
+# 物料文档格式
+
+## 使用模板
+
+**模板文件**: `./templates/material.mdx`
+
+文档必须严格按照模板格式编写,包含以下章节:
+1. Import 语句
+2. 标题和简介(带可选配图)
+3. 案例演示(基本使用 + 高级用法)
+4. API 参考(Props 表格)
+5. 源码导读(目录结构、核心实现、流程图、依赖梳理)
+
+## 参考示例
+
+- [`dynamic-value-input.mdx`](apps/docs/src/zh/materials/components/dynamic-value-input.mdx) - 完整的流程图和依赖说明
+- [`variable-selector.mdx`](apps/docs/src/zh/materials/components/variable-selector.mdx) - 多个 API 表格和警告提示
+
+## 关键注意事项
+
+**API 表格要求**:
+- 必须包含所有公开的 Props
+- 类型使用反引号(如 \`string\`)
+- 描述清晰简洁
+- 多个相关类型分开列表
+
+**源码导读要求**:
+- 目录结构:展示文件列表及说明
+- 核心实现:用代码片段说明关键逻辑
+- 整体流程:Mermaid 流程图(推荐)
+- 依赖梳理:分类列出 FlowGram API、其他物料、第三方库
+
+---
+
+# 图片处理指南
+
+## 截图要求
+
+1. **时机**: Story 组件完成后,运行 docs 站点截图
+2. **内容**: 捕获物料的典型使用状态,清晰可见
+3. **格式**: PNG,适当压缩
+
+## 命名和存储
+
+- **命名**: `{物料名称}.png`(kebab-case)
+- **存储**: `apps/docs/src/public/materials/{物料名称}.png`
+- **引用**: `/materials/{物料名称}.png`
+
+## 在文档中使用
+
+```mdx
+<br />
+<div>
+  <img loading="lazy" src="/materials/{物料名称}.png" alt="{物料名称} 组件" style={{ width: '50%' }} />
+</div>
+```
+
+---
+
+# 翻译流程
+
+## 翻译时机
+
+- ✅ 用户明确要求翻译
+- ✅ 中文文档已经用户审核确认
+- ❌ 文档还在修改中
+- ❌ 用户未确认最终版本
+
+## 翻译原则
+
+**术语一致性**:
+- ComponentName → ComponentName(组件名不翻译)
+- Props、Hook、Schema 等术语保持原文
+
+**代码不翻译**:
+- 所有代码块、命令、路径保持原样
+
+**链接处理**:
+- 内部链接:`/zh/` → `/en/`
+- 外部链接和 GitHub 链接:保持不变
+
+**格式保持**:
+- Markdown 格式、缩进、空行完全一致
+
+## 翻译检查清单
+
+- [ ] 标题和描述已翻译
+- [ ] 代码示例未被翻译
+- [ ] 命令和路径保持原样
+- [ ] 内部文档链接已更新
+- [ ] API 表格描述列已翻译
+- [ ] Mermaid 图中文节点已翻译
+- [ ] 术语使用一致
+
+---
+
+# 最佳实践
+
+## Props 提取技巧
+
+1. 查找 `interface` 或 `type` 定义
+2. 检查组件函数参数类型
+3. 查找 `defaultProps` 确认默认值
+4. 阅读 JSDoc 提取描述
+
+## 依赖分析方法
+
+1. 查看 import 语句(直接依赖)
+2. 分析 Hook 调用(FlowGram API)
+3. 查找组件引用(其他物料)
+4. 检查 package.json(第三方库)
+
+## Mermaid 流程图建议
+
+1. 简洁明了,关注核心流程
+2. 使用时序图绘制
+
+## 常见错误避免
+
+❌ 直接导入物料而不使用 `React.lazy`
+❌ API 表格遗漏 Props
+❌ 依赖链接失效
+❌ 中英文混用
+❌ 路径格式错误
+
+✅ 参考优秀示例
+✅ 仔细阅读源码
+✅ 验证所有链接
+✅ 保持语言和格式一致
+✅ 使用项目约定的路径格式
+
+---
+
+# 相关工具和资源
+
+## 开发命令
+
+```bash
+# 启动文档站点
+rush dev:docs
+
+# 查看修改
+git diff
+git diff --cached
+```
+
+## 关键目录
+
+| 目录 | 说明 |
+|------|------|
+| `packages/materials/form-materials/src/components` | 物料源码 |
+| `apps/docs/src/zh/materials/components` | 中文文档 |
+| `apps/docs/src/en/materials/components` | 英文文档 |
+| `apps/docs/components/form-materials/components` | Story 组件 |
+| `apps/docs/src/public/materials` | 图片资源 |
+| `./templates` | 文档模板 |
+

+ 172 - 0
.claude/skills/material-component-doc/templates/material.mdx

@@ -0,0 +1,172 @@
+import { SourceCode } from '@theme';
+import { BasicStory, WithSchemaStory } from 'components/form-materials/components/{物料名称}';
+
+# ComponentName
+
+ComponentName 是一个用于...的组件,它支持...功能。[用 1-2 段文字描述物料的核心功能、使用场景和主要特性]
+
+<br />
+<div>
+  <img loading="lazy" src="/materials/{物料名称}.png" alt="ComponentName 组件" style={{ width: '50%' }} />
+</div>
+
+## 案例演示
+
+### 基本使用
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { ComponentName } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<ValueType> name="field_name">
+        {({ field }) => (
+          <ComponentName
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+### 高级用法示例(根据物料特性添加)
+
+<WithSchemaStory />
+
+```tsx pure title="form-meta.tsx"
+import { ComponentName } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<ValueType> name="field_name">
+        {({ field }) => (
+          <ComponentName
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'string' }}
+            // 其他高级配置...
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API 参考
+
+### ComponentName Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `value` | `ValueType` | - | 组件的值 |
+| `onChange` | `(value: ValueType) => void` | - | 值变化时的回调函数 |
+| `readonly` | `boolean` | `false` | 是否为只读模式 |
+| `hasError` | `boolean` | `false` | 是否显示错误状态 |
+| `style` | `React.CSSProperties` | - | 自定义样式 |
+
+### RelatedConfigType(如果有相关的配置类型)
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `property1` | `string` | - | 属性说明 |
+| `property2` | `boolean` | `false` | 属性说明 |
+
+### RelatedProviderProps(如果有 Provider 组件)
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `children` | `React.ReactNode` | - | 子组件 |
+| `config` | `ConfigType` | - | 配置对象 |
+
+## 源码导读
+
+<SourceCode
+  href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/{物料路径}"
+/>
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/{物料路径}
+```
+
+### 目录结构讲解
+
+```
+{物料名称}/
+├── index.tsx           # 主组件实现,包含 ComponentName 核心逻辑
+├── hooks.ts            # 自定义 Hooks,处理... [如果有]
+├── context.tsx         # Context Provider,提供... [如果有]
+├── utils.ts            # 工具函数,用于... [如果有]
+└── styles.css          # 样式文件
+```
+
+### 核心实现说明
+
+#### 功能点1
+[用简洁的文字描述实现原理]
+
+```typescript
+// 展示关键代码片段
+const result = useHookName(props);
+```
+
+#### 功能点2
+[描述另一个关键功能的实现方式]
+
+```typescript
+// 展示关键逻辑
+if (condition) {
+  return <ComponentA />;
+} else {
+  return <ComponentB />;
+}
+```
+
+### 整体流程
+
+```mermaid
+graph TD
+    A[组件初始化] --> B{判断条件}
+    B -->|条件1| C[执行分支A]
+    B -->|条件2| D[执行分支B]
+
+    C --> E[处理用户交互]
+    D --> F[处理数据变化]
+
+    E --> G[触发 onChange 回调]
+    F --> G
+```
+
+### 使用到的 FlowGram API
+
+[**@flowgram.ai/package-name**](https://github.com/bytedance/flowgram.ai/tree/main/packages/path)
+- [`ApiName`](https://flowgram.ai/auto-docs/package/type/ApiName): API 的功能说明
+- [`HookName`](https://flowgram.ai/auto-docs/package/functions/HookName): Hook 的功能说明
+
+[**@flowgram.ai/another-package**](https://github.com/bytedance/flowgram.ai/tree/main/packages/another-path)
+- [`TypeName`](https://flowgram.ai/auto-docs/package/interfaces/TypeName): 类型定义说明
+
+### 依赖的其他物料
+
+[**DependentMaterial**](./dependent-material) 物料的简要说明
+- `ExportedComponent`: 导出组件的用途
+- `ExportedHook`: 导出 Hook 的用途
+
+[**AnotherMaterial**](./another-material) 物料的简要说明
+
+### 使用的第三方库
+
+[**library-name**](https://library-url.com) 库的说明
+- `ImportedComponent`: 组件的用途
+- `importedFunction`: 函数的用途

+ 16 - 0
AGENTS.md

@@ -0,0 +1,16 @@
+# Repository Guidelines
+
+## Project Structure & Module Organization
+FlowGram is a Rush-managed monorepo. Production-ready libraries live under `packages/*` (canvas engine, node engine, runtime, plugins). Demo UIs and docs sit inside `apps/*` (for example `apps/demo-free-layout`, `apps/docs`). Shared tooling, config, and scripts live under `common/` and `config/`. End-to-end Playwright suites are isolated in `e2e/<scenario>` so they can be installed and run independently. New code should land in the closest existing package; create additional Rush projects only when a module needs its own version and publish cycle.
+
+## Build, Test, and Development Commands
+Use Node.js 18 LTS with pnpm 10.6.5 (Rush enforces versions). Install dependencies via `rush install`. Run `rush build` to compile every registered project. Use `rush dev:docs` or `rush dev:demo-free-layout` for hot-reload docs and demos. `rush lint`, `rush lint:fix`, and `rush ts-check` keep lint/TS diagnostics consistent. `rush test` aggregates unit tests; `rush e2e:test` runs Playwright suites, while `rush e2e:update-screenshot` refreshes snapshots.
+
+## Coding Style & Naming Conventions
+We write TypeScript with React, sharing configs from `config/eslint-config`. ESLint enforces 2-space indentation, semicolons, and import order; run `rush lint:fix` before committing. Use `PascalCase` for React components and classes, `camelCase` for variables/functions, and `SCREAMING_SNAKE_CASE` only for constants exported from config files. File names follow kebab-case (e.g., `flow-node-form.tsx`). Keep public API surfaces documented via barrel files such as `packages/canvas-engine/core/src/index.ts`.
+
+## Testing Guidelines
+Unit tests use Vitest and live beside source in `__tests__` folders or `*.test.ts` files; prefer descriptive names like `node-service.test.ts`. Ensure new logic is covered by `rush test`, and include data fixtures where possible. Playwright specs under `e2e/*/tests` cover critical workflows—coordinate UI changes with updated snapshots and run `rush e2e:test --to <package>` to scope failures.
+
+## Commit & Pull Request Guidelines
+Follow conventional commits (`type(scope): subject`) as seen in history (`fix(auto-layout): ...`). Keep subjects imperative and ≤72 characters, with optional bodies for context. PRs must describe the change, link GitHub issues, and attach before/after screenshots for UI updates. Confirm CI status, note any follow-ups, and request reviewers from the owning package tags (see `rush.json`).

+ 233 - 0
CLAUDE.md

@@ -0,0 +1,233 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Repository Overview
+
+FlowGram is a composable, visual workflow development framework built as a Rush-managed monorepo. It provides tools for building AI workflow platforms, including a flow canvas, node configuration forms, variable scope chains, and pre-built materials (LLM, Condition, Code Editor, etc.).
+
+## Build System & Package Management
+
+This monorepo uses **Rush 5.150.0** with **pnpm 10.6.5** as the package manager. Node.js version must be >=18.20.3 <19.0.0 || >=20.14.0 <23.0.0.
+
+### Essential Commands
+
+```bash
+# Install dependencies (required first step)
+rush install
+
+# Build all packages
+rush build
+
+# Build specific package and its dependencies
+rush build --to @flowgram.ai/core
+
+# Lint all packages
+rush lint
+
+# Fix lint issues
+rush lint:fix
+
+# TypeScript type checking
+rush ts-check
+
+# Run unit tests
+rush test
+
+# Run tests with coverage
+rush test:cov
+
+# Build packages in watch mode (for development)
+rush build:watch
+
+# E2E tests with Playwright
+rush e2e:test
+
+# Update E2E screenshots
+rush e2e:update-screenshot
+```
+
+### Development Commands for Demos
+
+```bash
+# Run docs site with hot reload
+rush dev:docs
+
+# Run specific demo apps with hot reload
+rush dev:demo-free-layout
+rush dev:demo-fixed-layout
+rush dev:demo-fixed-layout-simple
+rush dev:demo-free-layout-simple
+rush dev:demo-nextjs
+rush dev:demo-nextjs-antd
+```
+
+These commands use `concurrently` to run `rush build:watch` for dependencies alongside the demo's dev server.
+
+### Single Package Development
+
+To work on a single package in isolation:
+```bash
+cd packages/canvas-engine/core
+rushx build        # Runs the build script for this package only
+rushx test         # Runs tests for this package only
+rushx ts-check     # Type checks this package only
+```
+
+## Monorepo Structure
+
+### Core Organization
+
+- **`packages/`** - Production libraries organized by functional area:
+  - `canvas-engine/` - Canvas rendering and layout systems (core, document, renderer, fixed-layout-core, free-layout-core)
+  - `node-engine/` - Node data and form management (node, form, form-core)
+  - `variable-engine/` - Variable scoping and type inference (variable-core, variable-layout, json-schema)
+  - `runtime/` - Workflow execution engines (interface, js-core, nodejs)
+  - `plugins/` - Extensibility modules (23+ plugins for features like history, drag, snap, minimap, etc.)
+  - `client/` - High-level React components (editor, fixed-layout-editor, free-layout-editor, playground-react)
+  - `materials/` - Pre-built node materials (form-materials, form-antd-materials, fixed-semi-materials, coze-editor, type-editor)
+  - `common/` - Shared utilities (utils, reactive, command, history, history-storage, i18n)
+
+- **`apps/`** - Demos and documentation:
+  - `docs/` - Main documentation site
+  - `demo-*/` - Example applications (free-layout, fixed-layout, nextjs, vite, playground, etc.)
+  - `create-app/`, `cli/` - CLI tools for scaffolding
+
+- **`e2e/`** - End-to-end test suites (fixed-layout, free-layout)
+- **`config/`** - Shared configuration (eslint-config, ts-config)
+- **`common/`** - Rush tooling and scripts
+
+### Architectural Layers
+
+FlowGram is architected in distinct layers:
+
+1. **Canvas Engine Layer** (`@flowgram.ai/core`, `@flowgram.ai/document`, `@flowgram.ai/renderer`)
+   - Core abstractions for canvas rendering, document model, and viewport management
+   - Supports two layout modes: free-layout (drag-anywhere) and fixed-layout (structured positioning)
+   - Plugin-based architecture using dependency injection (inversify)
+
+2. **Node Engine Layer** (`@flowgram.ai/node`, `@flowgram.ai/form`, `@flowgram.ai/form-core`)
+   - Manages node data structures and lifecycle
+   - Form engine with validation, side effects, linkage, and error capture
+   - Uses `FormModelV2` (exported as `FormModel` from `@flowgram.ai/editor`)
+
+3. **Variable Engine Layer** (`@flowgram.ai/variable-core`, `@flowgram.ai/json-schema`)
+   - Provides variable scoping, structure inspection, and type inference
+   - Manages data flow constraints across workflow nodes
+   - Scope chain mechanism for variable resolution
+
+4. **Runtime Layer** (`@flowgram.ai/runtime-js`, `@flowgram.ai/runtime-nodejs`, `@flowgram.ai/runtime-interface`)
+   - Executes workflows in JavaScript/Node.js environments
+   - Interface package defines runtime contracts
+   - Separate implementations for browser and server
+
+5. **Client/Editor Layer** (`@flowgram.ai/editor`, `@flowgram.ai/fixed-layout-editor`, `@flowgram.ai/free-layout-editor`)
+   - High-level React components that integrate all subsystems
+   - `@flowgram.ai/editor` is the main barrel export for fixed-layout workflows
+   - Re-exports from core, form, variable, and plugin packages
+
+6. **Plugin Ecosystem**
+   - 20+ plugins providing features like drag-and-drop, history/undo, snap-to-grid, minimap, auto-layout, etc.
+   - Plugins are registered via dependency injection containers
+   - Naming convention: `free-*-plugin` for free-layout, `fixed-*-plugin` for fixed-layout, or generic plugins
+
+## Key Design Patterns
+
+### Dependency Injection
+The codebase heavily uses **inversify** for dependency injection. Services are decorated with `@injectable()` and injected via `@inject()`. Container modules organize related services.
+
+### Reactive State Management
+Uses a custom reactive system (`@flowgram.ai/reactive`) with React hooks:
+- `ReactiveState` and `ReactiveBaseState` for observable state
+- `useReactiveState`, `useReadonlyReactiveState`, `useObserve` hooks
+- `Tracker` for dependency tracking
+
+### Command Pattern
+`@flowgram.ai/command` provides a command/command registry system for undo/redo operations. Re-exported by `@flowgram.ai/core`.
+
+### Plugin Architecture
+Plugins extend functionality via:
+- `Plugin` interface from `@flowgram.ai/core`
+- Registration through container modules
+- Lifecycle hooks (`onInit`, `onDestroy`, etc.)
+
+## Testing
+
+- **Unit tests**: Use Vitest, located in `__tests__/` folders or `*.test.ts` files
+- **E2E tests**: Use Playwright, located in `e2e/*/tests/` directories
+- Run all tests: `rush test`
+- Run E2E tests for specific package: `rush e2e:test --to @flowgram.ai/e2e-free-layout`
+- Update Playwright snapshots: `rush e2e:update-screenshot`
+
+## Code Quality
+
+### Linting & Type Checking
+- ESLint configuration in `config/eslint-config` enforces 2-space indentation, semicolons, and import order
+- TypeScript config in `config/ts-config`
+- Always run `rush lint:fix` before committing
+- Run `rush ts-check` to validate TypeScript across all packages
+
+### Naming Conventions
+- **React components/classes**: PascalCase
+- **Variables/functions**: camelCase
+- **Constants**: SCREAMING_SNAKE_CASE (only for exported config)
+- **File names**: kebab-case (e.g., `flow-node-form.tsx`)
+
+### Pre-commit Hooks
+- `rush lint-staged` - Runs linting on staged files
+- `rush commitlint` - Validates commit message format (conventional commits)
+
+### Dependency Checks
+- `rush check-circular-dependency` - Detects circular dependencies
+- `rush dep-check` - Validates dependency consistency
+
+## Commit & Pull Request Standards
+
+Follow **conventional commits** format: `type(scope): subject`
+
+Examples from recent history:
+- `fix(auto-layout): rankdir top to bottom`
+- `feat(landing): hover logo node glowing`
+- `docs(variable): optimize variable docs by codex`
+
+Keep commit subjects imperative, ≤72 characters. Reference GitHub issues in PR descriptions.
+
+## Working with Packages
+
+### Adding a New Package
+1. Create folder under appropriate category (`packages/<category>/<package-name>`)
+2. Add entry to `rush.json` "projects" array with:
+   - `packageName`: `@flowgram.ai/<package-name>`
+   - `projectFolder`: relative path
+   - `versionPolicyName`: typically "publishPolicy" for libraries, "appPolicy" for apps
+   - `tags`: for categorization
+3. Run `rush update` to link the package
+
+### Publishing Workflow
+Packages with `versionPolicyName: "publishPolicy"` are publishable to npm. Apps use `"appPolicy"`.
+
+### Inter-package Dependencies
+Use `workspace:^x.x.x` protocol in package.json for internal dependencies. Rush will link them locally during development.
+
+## Common Issues
+
+### Build Failures
+- Ensure `rush install` was run after pulling changes
+- Check Node.js version matches `nodeSupportedVersionRange` in rush.json
+- Clear incremental build cache: delete `common/temp` and rebuild
+
+### Type Errors in Editor Packages
+The main editor packages (`@flowgram.ai/editor`, `@flowgram.ai/fixed-layout-editor`, `@flowgram.ai/free-layout-editor`) re-export many types. Look for type definitions in their upstream dependencies (@flowgram.ai/form, @flowgram.ai/core, @flowgram.ai/node).
+
+### Plugin Registration
+Plugins must be registered in a dependency injection container. Check demo apps for examples of container module setup.
+
+### Rush Command Not Found
+Ensure Rush is installed globally: `npm install -g @microsoft/rush`
+Or use the install-run script: `node common/scripts/install-run-rush.js <command>`
+
+## Additional Resources
+
+- Documentation: https://flowgram.ai
+- Issues: https://github.com/bytedance/flowgram.ai/issues
+- Contributing: See CONTRIBUTING.md

+ 71 - 0
apps/docs/components/form-materials/components/assign-row.tsx

@@ -0,0 +1,71 @@
+/**
+ * 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 { AssignValueType } from '@flowgram.ai/form-materials';
+
+import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const AssignRow = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.AssignRow,
+  }))
+);
+
+export const AssignModeStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<AssignValueType | undefined>
+            defaultValue={{
+              operator: 'assign',
+              left: { type: 'ref', content: ['start_0', 'str'] },
+              right: { type: 'constant', content: 'Hello World', schema: { type: 'string' } },
+            }}
+            name="assign_row"
+          >
+            {({ field }) => (
+              <AssignRow value={field.value} onChange={(value) => field.onChange(value)} />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);
+
+export const DeclareModeStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<AssignValueType | undefined> name="assign_row">
+            {({ field }) => (
+              <AssignRow
+                value={{
+                  operator: 'declare',
+                  left: 'newVariable',
+                  right: {
+                    type: 'constant',
+                    content: 'Hello World',
+                    schema: { type: 'string' },
+                  },
+                }}
+                onChange={(value) => field.onChange(value)}
+              />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);

+ 28 - 0
apps/docs/components/form-materials/components/assign-rows.tsx

@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React from 'react';
+
+import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const AssignRows = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.AssignRows,
+  }))
+);
+
+export const BasicStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <AssignRows name="assign_rows" />
+        </>
+      ),
+    }}
+  />
+);

+ 58 - 0
apps/docs/components/form-materials/components/batch-variable-selector.tsx

@@ -0,0 +1,58 @@
+/**
+ * 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 { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const BatchVariableSelector = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.BatchVariableSelector,
+  }))
+);
+
+const VariableSelector = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.VariableSelector,
+  }))
+);
+
+export const BasicStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <div style={{ marginBottom: 16 }}>
+            <div style={{ marginBottom: 8, fontSize: 12, color: '#666' }}>
+              BatchVariableSelector (Array variables only):
+            </div>
+            <Field<string[] | undefined> name="batch_variable">
+              {({ field }) => (
+                <BatchVariableSelector
+                  value={field.value}
+                  onChange={(value) => field.onChange(value)}
+                />
+              )}
+            </Field>
+          </div>
+          <div>
+            <div style={{ marginBottom: 8, fontSize: 12, color: '#666' }}>
+              VariableSelector (All variables):
+            </div>
+            <Field<string[] | undefined> name="normal_variable">
+              {({ field }) => (
+                <VariableSelector value={field.value} onChange={(value) => field.onChange(value)} />
+              )}
+            </Field>
+          </div>
+        </>
+      ),
+    }}
+  />
+);

+ 152 - 0
apps/docs/components/form-materials/components/constant-inputs.tsx

@@ -0,0 +1,152 @@
+/**
+ * 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 { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const ConstantInput = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.ConstantInput,
+  }))
+);
+
+export const BasicStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterStartNode
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
+            <b>String</b>
+            <Field<string> name="constant_string" defaultValue="Hello World">
+              {({ field }) => (
+                <ConstantInput
+                  value={field.value}
+                  onChange={(value) => field.onChange(value)}
+                  schema={{ type: 'string' }}
+                />
+              )}
+            </Field>
+
+            <b>Number</b>
+            <Field<number> name="constant_number" defaultValue={42}>
+              {({ field }) => (
+                <ConstantInput
+                  value={field.value}
+                  onChange={(value) => field.onChange(value)}
+                  schema={{ type: 'number' }}
+                />
+              )}
+            </Field>
+
+            <b>Boolean</b>
+            <Field<boolean> name="constant_boolean" defaultValue={true}>
+              {({ field }) => (
+                <ConstantInput
+                  value={field.value}
+                  onChange={(value) => field.onChange(value)}
+                  schema={{ type: 'boolean' }}
+                />
+              )}
+            </Field>
+
+            <b>Object</b>
+            <Field<string>
+              name="constant_object"
+              defaultValue={JSON.stringify({ key: 'value', nested: { data: 'test' } })}
+            >
+              {({ field }) => (
+                <ConstantInput
+                  value={field.value}
+                  onChange={(value) => field.onChange(value)}
+                  schema={{ type: 'object' }}
+                />
+              )}
+            </Field>
+
+            <b>Array</b>
+            <Field<string>
+              name="constant_array"
+              defaultValue={JSON.stringify([1, 2, 3, 'four', true])}
+            >
+              {({ field }) => (
+                <ConstantInput
+                  value={field.value}
+                  onChange={(value) => field.onChange(value)}
+                  schema={{ type: 'array' }}
+                />
+              )}
+            </Field>
+          </div>
+        </>
+      ),
+    }}
+  />
+);
+
+export const FallbackRendererStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterStartNode
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<any>
+            name="constant_fallback"
+            defaultValue={{ custom: 'data', type: 'unsupported' }}
+          >
+            {({ field }) => (
+              <ConstantInput
+                value={field.value}
+                onChange={(value) => field.onChange(value)}
+                schema={{ type: 'custom-unsupported-type' }}
+                fallbackRenderer={({ value, onChange, readonly }) => (
+                  <div style={{ padding: '8px', background: '#f0f0f0', border: '1px dashed #ccc' }}>
+                    <p>Fallback renderer for unsupported type</p>
+                  </div>
+                )}
+              />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);
+
+export const CustomStrategyStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterStartNode
+    filterEndNode
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<string> name="constant_custom" defaultValue="Custom Value">
+            {({ field }) => (
+              <ConstantInput
+                value={field.value}
+                onChange={(value) => field.onChange(value)}
+                schema={{ type: 'object' }}
+                strategies={[
+                  {
+                    hit: (schema) => schema.type === 'object',
+                    Renderer: ({ value, onChange, readonly }) => <p>Object is not supported now</p>,
+                  },
+                ]}
+              />
+            )}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);

+ 96 - 0
apps/docs/components/form-materials/components/display-outputs.tsx

@@ -0,0 +1,96 @@
+/**
+ * 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 { provideJsonSchemaOutputs, type IJsonSchema } from '@flowgram.ai/form-materials';
+
+import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const DisplayOutputs = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.DisplayOutputs,
+  }))
+);
+
+const JsonSchemaEditor = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.JsonSchemaEditor,
+  }))
+);
+
+export const DisplayFromScopeStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    filterStartNode
+    transformInitialNode={{
+      custom_0: (node) => {
+        node.data.outputs = {
+          type: 'object',
+          properties: {
+            result: { type: 'string' },
+            status: { type: 'number' },
+          },
+        };
+        return node;
+      },
+    }}
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<IJsonSchema | undefined> name="outputs">
+            {({ field }) => (
+              <JsonSchemaEditor value={field.value} onChange={(value) => field.onChange(value)} />
+            )}
+          </Field>
+          <br />
+          <b>Display Outputs by Scope:</b>
+          <DisplayOutputs displayFromScope />
+        </>
+      ),
+      effect: {
+        outputs: provideJsonSchemaOutputs,
+      },
+    }}
+  />
+);
+
+export const DisplayFromFieldStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    filterStartNode
+    transformInitialNode={{
+      custom_0: (node) => {
+        node.data.outputs = {
+          type: 'object',
+          properties: {
+            result: { type: 'string' },
+            status: { type: 'number' },
+          },
+        };
+        return node;
+      },
+    }}
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <Field<IJsonSchema | undefined> name="outputs">
+            {({ field }) => (
+              <JsonSchemaEditor value={field.value} onChange={(value) => field.onChange(value)} />
+            )}
+          </Field>
+          <br />
+          <b>Display Outputs By Schema</b>
+          <Field<IJsonSchema | undefined> name="outputs">
+            {({ field }) => <DisplayOutputs value={field.value} />}
+          </Field>
+        </>
+      ),
+    }}
+  />
+);

+ 90 - 0
apps/docs/components/form-materials/form-plugins/infer-assign-plugin.tsx

@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React from 'react';
+
+import { createInferAssignPlugin } from '@flowgram.ai/form-materials';
+
+import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const AssignRows = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.AssignRows,
+  }))
+);
+
+const DisplayOutputs = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.DisplayOutputs,
+  }))
+);
+
+export const BasicStory = () => (
+  <FreeFormMetaStoryBuilder
+    transformInitialNode={{
+      end_0: (node) => {
+        node.data.inputsValues = {
+          info: {
+            type: 'ref',
+            content: ['custom_0', 'userInfo'],
+          },
+        };
+
+        return node;
+      },
+    }}
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <AssignRows
+            name="assign"
+            defaultValue={[
+              // 从常量声明变量
+              {
+                operator: 'declare',
+                left: 'userName',
+                right: {
+                  type: 'constant',
+                  content: 'John Doe',
+                  schema: { type: 'string' },
+                },
+              },
+              // 从变量声明变量
+              {
+                operator: 'declare',
+                left: 'userInfo',
+                right: {
+                  type: 'ref',
+                  content: ['start_0', 'obj'],
+                },
+              },
+              // 赋值现有变量
+              {
+                operator: 'assign',
+                left: {
+                  type: 'ref',
+                  content: ['start_0', 'str'],
+                },
+                right: {
+                  type: 'constant',
+                  content: 'Hello Flowgram',
+                  schema: { type: 'string' },
+                },
+              },
+            ]}
+          />
+          <DisplayOutputs displayFromScope style={{ marginTop: 10 }} />
+        </>
+      ),
+      plugins: [
+        createInferAssignPlugin({
+          assignKey: 'assign',
+          outputKey: 'outputs',
+        }),
+      ],
+    }}
+  />
+);

+ 104 - 0
apps/docs/components/form-materials/form-plugins/infer-inputs-plugin.tsx

@@ -0,0 +1,104 @@
+/**
+ * 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 { createInferInputsPlugin } from '@flowgram.ai/form-materials';
+
+import { FreeFormMetaStoryBuilder, FormHeader } from '../../free-form-meta-story-builder';
+
+const InputsValues = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.InputsValues,
+  }))
+);
+
+const InputsValuesTree = React.lazy(() =>
+  import('@flowgram.ai/form-materials').then((module) => ({
+    default: module.InputsValuesTree,
+  }))
+);
+
+/**
+ * Basic usage story - demonstrates automatic schema inference from InputsValues
+ */
+export const BasicStory = () => (
+  <FreeFormMetaStoryBuilder
+    filterEndNode
+    height={500}
+    formMeta={{
+      render: () => (
+        <>
+          <FormHeader />
+          <div>
+            <div>
+              <h4>Headers</h4>
+              <Field<Record<string, any> | undefined>
+                name="headersValues"
+                defaultValue={{
+                  'Content-Type': {
+                    type: 'constant',
+                    content: 'application/json',
+                    schema: { type: 'string' },
+                  },
+                  Authorization: {
+                    type: 'ref',
+                    content: ['start_0', 'str'],
+                  },
+                }}
+              >
+                {({ field }) => (
+                  <InputsValues value={field.value} onChange={(value) => field.onChange(value)} />
+                )}
+              </Field>
+            </div>
+
+            <div>
+              <h4>Body</h4>
+              <Field<Record<string, any> | undefined>
+                name="bodyValues"
+                defaultValue={{
+                  page: {
+                    index: {
+                      type: 'ref',
+                      content: ['start_0', 'obj', 'obj2', 'num'],
+                    },
+                    size: {
+                      type: 'constant',
+                      content: 10,
+                      schema: { type: 'number' },
+                    },
+                  },
+                  query: {
+                    type: 'ref',
+                    content: ['start_0', 'obj'],
+                  },
+                }}
+              >
+                {({ field }) => (
+                  <InputsValuesTree
+                    value={field.value}
+                    onChange={(value) => field.onChange(value)}
+                  />
+                )}
+              </Field>
+            </div>
+          </div>
+        </>
+      ),
+      plugins: [
+        createInferInputsPlugin({
+          sourceKey: 'headersValues',
+          targetKey: 'headersSchema',
+        }),
+        createInferInputsPlugin({
+          sourceKey: 'bodyValues',
+          targetKey: 'bodySchema',
+        }),
+      ],
+    }}
+  />
+);

+ 156 - 5
apps/docs/src/en/materials/components/assign-row.mdx

@@ -1,11 +1,162 @@
 import { SourceCode } from '@theme';
+import { AssignModeStory, DeclareModeStory } from 'components/form-materials/components/assign-row';
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
-:::
+# AssignRow
 
-# AssignRow (WIP)
+AssignRow is an assignment row component that supports two operation modes: **assignment mode (assign)** and **declaration mode (declare)**.
+
+- In assignment mode: the left side is a variable selector, and the right side is dynamic value input;
+- In declaration mode: the left side is a text input box, and the right side is dynamic value input.
+
+## Examples
+
+### Assignment Mode
+
+AssignRow **defaults to assignment mode**. In assignment mode, the left side is a variable selector and the right side is dynamic value input:
+
+<AssignModeStory />
+
+```tsx pure title="form-meta.tsx"
+import { AssignRow } from '@flowgram.ai/form-materials';
+import { AssignValueType } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<AssignValueType | undefined> name="assign_row">
+        {({ field }) => (
+          <AssignRow value={field.value} onChange={(value) => field.onChange(value)} />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+### Declaration Mode
+
+In declaration mode, the left side is variable name input and the right side is dynamic value input:
+
+<DeclareModeStory />
+
+```tsx pure title="form-meta.tsx"
+import { AssignRow } from '@flowgram.ai/form-materials';
+import { AssignValueType } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<AssignValueType | undefined> name="assign_row">
+        {({ field }) => (
+          <AssignRow
+            value={{
+              operator: 'declare',
+              left: 'newVariable',
+              right: {
+                type: 'constant',
+                content: 'Hello World',
+                schema: { type: 'string' },
+              },
+            }}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API Reference
+
+### AssignRow Props
+
+| Property | Type | Default | Description |
+|--------|------|--------|------|
+| `value` | `AssignValueType` | - | The value of the assignment row, containing operator, left value, and right value |
+| `onChange` | `(value?: AssignValueType) => void` | - | Callback function when value changes |
+| `onDelete` | `() => void` | - | Callback function when delete button is clicked |
+| `readonly` | `boolean` | `false` | Whether it is read-only mode |
+
+### AssignValueType
+
+```typescript
+type AssignValueType =
+  | {
+      operator: 'assign';
+      left?: IFlowRefValue;      // Variable reference
+      right?: IFlowValue;        // Dynamic value
+    }
+  | {
+      operator: 'declare';
+      left?: string;             // Variable name
+      right?: IFlowValue;        // Dynamic value
+    };
+```
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/assign-row"
-/>
+/>
+
+You can copy the source code locally using the CLI command:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/assign-row
+```
+
+### Directory Structure
+
+```
+assign-row/
+├── index.tsx     # Main implementation of AssignRow component
+└── types.ts      # Type definition file
+```
+
+### Core Implementation
+
+The core logic of the AssignRow component is to render different left input controls based on the `operator` field:
+
+1. **Assignment mode (`operator: 'assign'`)**: Renders `InjectVariableSelector` on the left for selecting existing variables
+2. **Declaration mode (`operator: 'declare'`)**: Renders `BlurInput` on the left for inputting new variable names
+3. **Unified right side**: Regardless of the mode, the right side renders `InjectDynamicValueInput`, supporting both constant and variable input
+
+#### Component Structure
+
+```mermaid
+graph TD
+    A[AssignRow Component] --> B{Determine operator type}
+    B -->|assign| C[Render variable selector]
+    B -->|declare| D[Render text input box]
+
+    C --> E[Right side dynamic value input]
+    D --> E
+
+    E --> F[Optional delete button]
+
+    C --> G[Support onDelete callback]
+    D --> G
+    F --> G
+```
+
+### Dependencies
+
+#### Other Components
+
+[**VariableSelector**](./variable-selector)
+- `InjectVariableSelector`: Dependency-injected variable selector
+
+[**DynamicValueInput**](./dynamic-value-input)
+- `InjectDynamicValueInput`: Dependency-injected dynamic value input component
+
+[**BlurInput**](./blur-input)
+- `BlurInput`: Blur input component
+
+#### Third-party Libraries
+
+[**Semi Design**](https://semi.design/zh-CN/)
+- `IconButton`: Icon button component
+- `IconMinus`: Minus icon

+ 105 - 4
apps/docs/src/en/materials/components/assign-rows.mdx

@@ -1,11 +1,112 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/components/assign-rows';
+
+# AssignRows
+
+AssignRows is an assignment row list component implemented based on `FieldArray`, supporting dynamic addition and deletion of assignment rows.
+
+The component provides two action buttons: **Assign** and **Declare**, which can add assignment mode and declaration mode assignment rows respectively. Each assignment row can be configured and deleted independently.
+
+:::tip
+
+`AssignRows` is typically used together with the [`infer-assign-plugin`](../form-plugins/infer-assign-plugin) form plugin to convert defined declarations into node output variables and achieve automatic type linkage.
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
 :::
 
-# AssignRows (WIP)
+## Examples
+
+### Basic Usage
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { AssignRows } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <AssignRows name="assign_rows" />
+    </>
+  ),
+}
+```
+
+## API Reference
+
+### AssignRows Props
+
+| Property | Type | Default | Description |
+|--------|------|--------|------|
+| `name` | `string` | - | Form field name for FieldArray |
+| `readonly` | `boolean` | `false` | Whether it is read-only mode |
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/assign-rows"
-/>
+/>
+
+You can copy the source code locally using the CLI command:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/assign-rows
+```
+
+### Directory Structure
+
+```
+assign-rows/
+└── index.tsx     # Main implementation of AssignRows component
+```
+
+### Core Implementation
+
+The core functionality of the AssignRows component is dynamic list management implemented based on `FieldArray`:
+
+1. **Dynamic Addition**: Provides two buttons to add assignment mode and declaration mode rows respectively
+2. **Dynamic Deletion**: Each row supports independent deletion operations
+3. **State Management**: Uses `FieldArray` to manage the state of the entire list
+4. **Component Reuse**: Each row reuses the `AssignRow` component
+
+#### Component Workflow
+
+```mermaid
+graph TD
+    A[AssignRows Component] --> B[FieldArray Wrapper]
+    B --> C[Render existing row list]
+    C --> D[Each row uses AssignRow]
+    D --> E[Supports onChange and onDelete]
+
+    B --> F[Add button area]
+    F --> G[Assign button]
+    F --> H[Declare button]
+
+    G --> I[Add assignment row]
+    H --> J[Add declaration row]
+
+    I --> K[Call field.append]
+    J --> K
+
+    E --> L[Call field.remove]
+```
+
+### Dependencies
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- `FieldArray`: Form array field component for managing dynamic lists
+- `FieldArrayRenderProps`: FieldArray render property types
+
+#### Other Components
+
+[**AssignRow**](./assign-row)
+- `AssignRow`: Assignment row component that handles single row logic
+- `AssignValueType`: Assignment row value type definition
+
+#### Third-party Libraries
+
+[**Semi Design**](https://semi.design/zh-CN/)
+- `Button`: Button component
+- `IconPlus`: Plus icon

+ 200 - 3
apps/docs/src/en/materials/components/batch-variable-selector.mdx

@@ -1,11 +1,208 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/components/batch-variable-selector';
+
+# BatchVariableSelector
+
+BatchVariableSelector is a component for selecting array-type variables. It's a wrapper around [VariableSelector](./variable-selector) that automatically filters the variable tree to show only array-type variables and provides private scope support. It's commonly used in batch processing scenarios (such as selecting loop data sources in Loop nodes).
+
+**Core Features:**
+
+- 🔍 **Auto Filtering**: Only displays array-type (`type: 'array'`) variables
+- 🔐 **Private Scope**: Provides isolated variable scope through [`PrivateScopeProvider`](../../guide/variable/concept#node-private-scope)
+- 🎯 **Specialized Scenarios**: Designed for batch processing, loops, and other scenarios requiring array data sources
+- 📦 **Ready to Use**: No need to manually configure schema filtering conditions, automatically applies array type constraints
+
+## Examples
+
+### Basic Usage
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { BatchVariableSelector, VariableSelector } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      {/* BatchVariableSelector only shows array-type variables */}
+      <Field<string[] | undefined> name="batch_variable">
+        {({ field }) => (
+          <BatchVariableSelector
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+
+      {/* VariableSelector shows all variable types */}
+      <Field<string[] | undefined> name="normal_variable">
+        {({ field }) => (
+          <VariableSelector
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API Reference
+
+### BatchVariableSelector Props
+
+BatchVariableSelector inherits all properties from [VariableSelector](./variable-selector), but the `includeSchema` property is fixed to array-type filtering and cannot be customized.
+
+| Property | Type | Default | Description |
+|----------|------|---------|-------------|
+| `value` | `string[]` | - | Selected variable path array |
+| `onChange` | `(value?: string[]) => void` | - | Callback when variable selection changes |
+| `config` | `VariableSelectorConfig` | `{}` | Configuration object (same as VariableSelector) |
+| `readonly` | `boolean` | `false` | Whether in read-only mode |
+| `hasError` | `boolean` | `false` | Whether to display error state |
+| `style` | `React.CSSProperties` | - | Custom styles |
+| `triggerRender` | `(props: TriggerRenderProps) => React.ReactNode` | - | Custom trigger renderer |
 
 :::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
+`includeSchema` and `excludeSchema` properties are not available in BatchVariableSelector, as the component internally uses `{ type: 'array', extra: { weak: true } }` as the fixed filtering condition.
 :::
 
-# BatchVariableSelector (WIP)
+### VariableSelectorConfig
+
+| Property | Type | Default | Description |
+|----------|------|---------|-------------|
+| `placeholder` | `string` | `'Select Variable'` | Placeholder text |
+| `notFoundContent` | `string` | `'Undefined'` | Content to display when variable is not found |
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/batch-variable-selector"
-/>
+/>
+
+Use the CLI command to copy the source code locally:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/batch-variable-selector
+```
+
+### Directory Structure
+
+```
+batch-variable-selector/
+└── index.tsx           # Main component implementation with BatchVariableSelector core logic
+```
+
+### Core Implementation
+
+#### Private Scope Mechanism
+
+BatchVariableSelector provides an independent variable scope for child components through [`PrivateScopeProvider`](../../guide/variable/concept#node-private-scope):
+
+```tsx
+<PrivateScopeProvider>
+  <VariableSelector {...props} includeSchema={batchVariableSchema} />
+</PrivateScopeProvider>
+```
+
+`PrivateScopeProvider` creates a [node private scope](../../guide/variable/concept#node-private-scope), which is crucial in batch processing scenarios:
+
+- **Loop variable isolation**: In Loop nodes, loop variables for each iteration (such as `item`, `index`) are stored in the private scope, preventing pollution of the external scope
+- **Avoid naming conflicts**: Temporary variables defined inside batch processing nodes will not conflict with external variable names
+- **Support nested structures**: Complex batch processing logic can define multi-level variable structures in the private scope
+- **Data security**: Variables in the private scope can only be accessed by the current node and its child nodes, ensuring data security
+
+:::info
+
+For more detailed information about scopes, please refer to the [Variable Concept Documentation](../../guide/variable/concept#variables-in-canvas).
+
+:::
+
+#### Array Type Filtering
+
+The component internally uses the following fixed schema for filtering:
+
+```typescript
+const batchVariableSchema: IJsonSchema = {
+  type: 'array',
+  extra: { weak: true },
+};
+```
+
+- `type: 'array'`: Only display array-type variables
+- `extra: { weak: true }`: Enable weak type matching, allowing potentially compatible types
+
+### Overall Flow
+
+```mermaid
+sequenceDiagram
+    participant User
+    participant BatchVariableSelector
+    participant PrivateScopeProvider
+    participant VariableSelector
+    participant useVariableTree
+    participant VariableTree
+
+    User->>BatchVariableSelector: Select array variable
+    BatchVariableSelector->>PrivateScopeProvider: Set private scope context
+    PrivateScopeProvider->>VariableSelector: Pass array filtering schema
+    VariableSelector->>useVariableTree: Get available variable list
+    useVariableTree->>VariableTree: Query variable tree data
+    VariableTree-->>useVariableTree: Return all variables
+    useVariableTree-->>VariableSelector: Filter array-type variables
+    VariableSelector-->>BatchVariableSelector: Render array variable selector
+    BatchVariableSelector-->>User: Display selectable array variables
+```
+
+### FlowGram APIs Used
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/plugins/node-variable-plugin)
+- [`PrivateScopeProvider`](https://flowgram.ai/auto-docs/node-variable-plugin/functions/PrivateScopeProvider): Context Provider for private variable scope
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable/json-schema)
+- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema type definition for variable type filtering
+
+### Dependent Materials
+
+[**VariableSelector**](./variable-selector) Base variable selector component
+- `VariableSelector`: Core variable selection component, BatchVariableSelector is its wrapper version
+- `VariableSelectorProps`: Property type definitions
+
+## FAQ
+
+### Why is PrivateScopeProvider needed?
+
+`PrivateScopeProvider` provides variable scope isolation, which is important in the following scenarios:
+
+1. **Loop Nodes**: In Loop nodes, each iteration needs an independent scope to store loop variables (such as `item`, `index`). Refer to [Variable Concept - Node Private Scope](../../guide/variable/concept#node-private-scope)
+2. **Nested Structures**: When there are nested variable declarations inside nodes, avoiding naming conflicts with external variables
+3. **Component Reuse**: Ensuring variables don't interfere with each other when the same component is used in different contexts
+4. **Data Security**: Variables in the private scope can only be accessed by the current node and its child nodes, ensuring data security
+
+For more information about scope chains and variable access permissions, please refer to [Variable Concept - Scope Chain](../../guide/variable/concept#scope-chain).
+
+### What's the difference between BatchVariableSelector and VariableSelector?
+
+| Feature | BatchVariableSelector | VariableSelector |
+|---------|----------------------|------------------|
+| Variable Type Filtering | Fixed to array type | Customizable |
+| Scope | Built-in private scope | Uses current scope |
+| Use Cases | Batch processing, loops, etc. | General variable selection |
+| Schema Configuration | Not configurable | Fully configurable |
+
+### How to get the actual value of the selected variable?
+
+BatchVariableSelector returns a variable path (`string[]`). To get the actual value, you need to use [`provideBatchInputEffect`](../effects/provide-batch-input) in the form's effect:
+
+```typescript
+export const formMeta = {
+  render: YourFormRender,
+  effect: {
+    yourFieldName: provideBatchInputEffect,
+  },
+};
+```
+
+`provideBatchInputEffect` automatically resolves variable references and injects them into the form data.

+ 168 - 4
apps/docs/src/en/materials/components/constant-input.mdx

@@ -1,11 +1,175 @@
 import { SourceCode } from '@theme';
+import { BasicStory, FallbackRendererStory, CustomStrategyStory } from 'components/form-materials/components/constant-inputs';
+
+# ConstantInput
+
+ConstantInput is a constant input component that automatically selects the appropriate input type renderer based on the provided JSON Schema.
+
+The component supports custom rendering strategies and fallback renderers, capable of handling constant inputs for various data types.
+
+## Examples
+
+### Basic Usage
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<string> name="constant_string" defaultValue="Hello World">
+        {({ field }) => (
+          <ConstantInput
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'string' }}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+:::tip{title="Register Constant Input for New Types"}
+
+Refer to [Type Management](../common/json-schema-preset) to configure constant inputs when registering types
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
 :::
 
-# ConstantInput (WIP)
+### Fallback Renderer
+
+When the component cannot find a suitable renderer, it will use the fallback renderer:
+
+<FallbackRendererStory />
+
+```tsx pure title="form-meta.tsx"
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<any> name="constant_fallback" defaultValue={{ custom: 'data' }}>
+        {({ field }) => (
+          <ConstantInput
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'custom-unsupported-type' }}
+            fallbackRenderer={({ value, onChange, readonly }) => (
+              <div style={{ padding: '8px', background: '#f0f0f0', border: '1px dashed #ccc' }}>
+                <p>Fallback renderer for unsupported type</p>
+              </div>
+            )}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+### Custom Strategy
+
+Use custom rendering strategies to override default behavior:
+
+<CustomStrategyStory />
+
+```tsx pure title="form-meta.tsx"
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<string> name="constant_custom" defaultValue="Custom Value">
+        {({ field }) => (
+          <ConstantInput
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'object' }}
+            strategies={[
+              {
+                hit: (schema) => schema.type === 'object',
+                Renderer: ({ value, onChange, readonly }) => (
+                  <p>Object is not supported now</p>
+                ),
+              },
+            ]}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API Reference
+
+### ConstantInput Props
+
+| Property | Type | Default | Description |
+|----------|------|---------|-------------|
+| `value` | `any` | - | Input value |
+| `onChange` | `(value: any) => void` | - | Callback function when value changes |
+| `schema` | `IJsonSchema` | - | JSON Schema used to determine the renderer |
+| `strategies` | `Strategy[]` | - | Array of custom rendering strategies |
+| `fallbackRenderer` | `React.FC<ConstantRendererProps>` | - | Fallback renderer used when no suitable renderer is found |
+| `readonly` | `boolean` | `false` | Whether it is read-only mode |
+
+### Strategy Interface
+
+```typescript
+interface Strategy<Value = any> {
+  hit: (schema: IJsonSchema) => boolean;
+  Renderer: React.FC<ConstantRendererProps<Value>>;
+}
+```
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/constant-input"
-/>
+/>
+
+Use CLI command to copy source code locally:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/constant-input
+```
+
+### Directory Structure
+
+```
+constant-input/
+├── index.tsx    # Main component implementation, contains ConstantInput core logic
+└── types.ts     # Type definitions, including Strategy interface and PropsType
+```
+
+### Core Implementation
+
+#### Renderer Selection Logic
+
+The component selects the appropriate renderer through the following steps:
+
+1. **Strategy Matching**: First checks if there are any strategies in the `strategies` array that match the current schema
+2. **Type Manager**: If no matching strategy is found, uses the type manager (`useTypeManager`) to get the renderer corresponding to the schema
+3. **Fallback Rendering**: If all above fail, uses the provided `fallbackRenderer` or the default disabled input box
+
+#### Type System Integration
+
+ConstantInput is deeply integrated with [**Material Type Management**](../common/json-schema-preset):
+
+- Gets the type manager through the `useTypeManager` Hook
+- Uses `typeManager.getTypeBySchema(schema)` to get the renderer for the corresponding type
+- Supports all JSON Schema standard types (string, number, boolean, object, array, etc.)
+
+### Dependencies
+
+#### flowgram API
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable/json-schema)
+- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema type definition
+- [`useTypeManager`](https://flowgram.ai/auto-docs/json-schema/functions/useTypeManager): Type manager Hook
+
+#### Third-party Libraries
+
+[**Semi UI**](https://semi.design/en-US)
+- Basic input component library, provides default input controls

+ 155 - 4
apps/docs/src/en/materials/components/coze-editor-extensions.mdx

@@ -1,11 +1,162 @@
 import { SourceCode } from '@theme';
+import { BasicStory as PromptWithVariablesStory } from 'components/form-materials/components/prompt-editor-with-variables';
+import { BasicStory as PromptWithInputsStory } from 'components/form-materials/components/prompt-editor-with-inputs';
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
+# CozeEditorExtensions
+
+CozeEditorExtensions is a set of functional extensions based on [coze-editor](https://github.com/coze-dev/rush-arch/tree/main/packages/text-editor), providing variable selection, Inputs selector, and variable tag echo capabilities.
+
+- `EditorVariableTree`: Monitors trigger characters like `@`/`{`, pops up an available variable tree, and writes the selected item into the editor.
+- `EditorVariableTagInject`: Renders `{{variable.path}}` text with markup, displaying variable icons, titles, and echo hints.
+- `EditorInputsTree`: Constructs a hierarchical tree based on node `inputsValues`, supporting insertion of `{{inputs.xxx}}` references in prompts.
+
+## Demo
+
+### Variable Tree + Tag Echo
+
+<PromptWithVariablesStory />
+
+```tsx pure title="prompt-editor-with-extensions.tsx"
+import {
+  PromptEditor,
+  EditorVariableTree,
+  EditorVariableTagInject,
+  EditorInputsTree,
+} from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <PromptEditor value={value} onChange={onChange}>
+      <EditorVariableTree triggerCharacters={TRIGGER_CHARACTERS} />
+      <EditorVariableTagInject />
+    </PromptEditor>
+  );
+}
+```
+
+:::tip{title="Trigger Method"}
+`EditorVariableTree` defaults to monitoring `{`, `{{`, and `@`. You can customize trigger characters through `triggerCharacters`.
 :::
 
-# CozeEditorExtensions (WIP)
+### Node Inputs Reference
+
+<PromptWithInputsStory />
+
+
+```tsx pure title="prompt-editor-with-extensions.tsx"
+import {
+  PromptEditor,
+  EditorVariableTree,
+  EditorVariableTagInject,
+  EditorInputsTree,
+} from '@flowgram.ai/form-materials';
+
+
+export function PromptEditorWithExtensions({ value, onChange, inputsValues }) {
+  return (
+    <PromptEditor value={value} onChange={onChange}>
+      <EditorInputsTree inputsValues={inputsValues} />
+    </PromptEditor>
+  );
+}
+```
+
+
+### Render Keys and Secondary Extension
+
+CozeEditorExtensions declares fixed `renderKey` through [`createInjectMaterial`](../common/inject-material):
+
+- `EditorVariableTree.renderKey = 'EditorVariableTree'`
+- `EditorVariableTagInject.renderKey = 'EditorVariableTagInject'`
+- `EditorInputsTree.renderKey = 'EditorInputsTree'`
+
+You can register renderers with the same name in `use-editor-props` to replace the default behavior. For example, customize the variable selection panel:
+
+```tsx pure title="override-variable-tree.tsx"
+import { useEditorProps } from '@flowgram.ai/editor';
+import { EditorVariableTree } from '@flowgram.ai/form-materials';
+import { CustomVariableTree } from './custom-variable-tree';
+
+export function useCustomEditorProps() {
+  return useEditorProps({
+    materials: {
+      components: {
+        [EditorVariableTree.renderKey!]: CustomVariableTree,
+      },
+    },
+  });
+}
+```
+
+
+## API Reference
+
+### EditorVariableTree Props
+
+| Property Name | Type | Default | Description |
+|--------|------|--------|------|
+| `triggerCharacters` | `string[]` | `['{', '{}', '@']` | Character set that triggers variable tree popup |
+
+### EditorVariableTagInject Props
+
+| Property Name | Type | Default | Description |
+|--------|------|--------|------|
+| _None_ | - | - | Component has no additional properties, rendering takes effect immediately |
+
+### EditorInputsTree Props
+
+| Property Name | Type | Default | Description |
+|--------|------|--------|------|
+| `inputsValues` | `IInputsValues` | - | Node Inputs key-value data, supports `FlowValue` reference |
+| `triggerCharacters` | `string[]` | `['{', '{}', '@']` | Character set that triggers Inputs selector |
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/coze-editor-extensions"
-/>
+/>
+
+Use CLI command to copy source code locally:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/coze-editor-extensions
+```
+
+### Directory Structure Explanation
+
+```
+coze-editor-extensions/
+├── index.tsx                 # Export injectable materials
+├── extensions/
+│   ├── inputs-tree.tsx       # Inputs Tree implementation
+│   ├── variable-tag.tsx      # Variable tag rendering
+│   └── variable-tree.tsx     # Variable tree selector
+└── styles.css                # Tag styles and popup styles
+```
+
+### Core Implementation Explanation
+
+**EditorVariableTree**
+- Popup positioning and scroll synchronization: `Mention` + `PositionMirror` combination ensures Popover always stays close to cursor position, scrolling triggers repositioning through `rePosKey`
+- Variable tree data source: `useVariableTree` reads variables registered in `Scope.available`, automatically applies schema filtering, disabled states, and icons
+
+**EditorVariableTagInject**
+- Tag rendering and subscription: Uses CodeMirror `MatchDecorator` to replace `{{xxx}}` text with `Tag` widget, and subscribes to variable title/Icon updates for real-time echo
+
+**EditorInputsTree**
+- Inputs tree construction: Supports both `FlowValue` and regular objects, recursively generates hierarchical nodes, and uniformly formats them as `{{path}}` before insertion
+
+### Dependencies
+
+#### Other Materials
+
+[**InjectMaterial**](../common/inject-material)
+- `createInjectMaterial`: Creates injectable material components
+
+#### Third-party Libraries
+
+[**coze-editor**](https://github.com/coze-dev/rush-arch/tree/main/packages/text-editor)
+- Base editor component
+
+[**CodeMirror MatchDecorator**](https://codemirror.net/docs/ref/#search.MatchDecorator)
+- Used for text matching and replacement of variable tags

+ 135 - 5
apps/docs/src/en/materials/components/display-outputs.mdx

@@ -1,11 +1,141 @@
 import { SourceCode } from '@theme';
+import { DisplayFromScopeStory, DisplayFromFieldStory } from 'components/form-materials/components/display-outputs';
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
-:::
+# DisplayOutputs
 
-# DisplayOutputs (WIP)
+DisplayOutputs is a component for visually displaying node output variables, supporting automatic retrieval of output variables from scope or manual specification of output schema through field values.
+
+## Demo
+
+### Getting Output Variables from Scope
+
+When `displayFromScope` is set to `true`, the component automatically retrieves output variables from the current node scope and displays them:
+
+<DisplayFromScopeStory />
+
+```tsx pure title="form-meta.tsx" {27}
+import { DisplayOutputs, provideJsonSchemaOutputs } from '@flowgram.ai/form-materials';
+import { Field } from '@flowgram.ai/editor';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<IJsonSchema | undefined> name="outputs">
+        {({ field }) => (
+          <JsonSchemaEditor value={field.value} onChange={(value) => field.onChange(value)} />
+        )}
+      </Field>
+      <p>Display Output Schema:</p>
+      <DisplayOutputs displayFromScope />
+    </>
+  ),
+  effect: {
+    outputs: provideJsonSchemaOutputs,
+  },
+}
+```
+
+### Specifying Output Schema through Field Value
+
+When `displayFromScope` is not set, the component receives the output JSON Schema through the `value` prop:
+
+<DisplayFromFieldStory />
+
+```tsx pure title="form-meta.tsx"
+import { DisplayOutputs } from '@flowgram.ai/form-materials';
+import { Field } from '@flowgram.ai/editor';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<IJsonSchema | undefined>
+        name="outputs"
+        defaultValue={{
+          type: 'object',
+          properties: {
+            result: { type: 'string' },
+            status: { type: 'number' },
+          },
+        }}
+      >
+        {({ field }) => (
+          <JsonSchemaEditor value={field.value} onChange={(value) => field.onChange(value)} />
+        )}
+      </Field>
+      <p>Display Output Schema:</p>
+      <Field<IJsonSchema | undefined> name="outputs">
+        {({ field }) => <DisplayOutputs value={field.value} />}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API Reference
+
+### DisplayOutputs Props
+
+| Property | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| value | `IJsonSchema` | - | JSON Schema object to display, used when `displayFromScope` is `false` |
+| displayFromScope | `boolean` | `false` | Whether to automatically get output variables from current scope |
+| showIconInTree | `boolean` | `false` | Whether to show icons in tree structure |
+| typeManager | `JsonSchemaTypeManager` | - | Custom type manager |
+| style | `React.CSSProperties` | - | Custom styles |
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/display-outputs"
-/>
+/>
+
+Copy source code locally using CLI command:
+
+```bash
+npx @flowgram.ai/cli@latest materials display-outputs
+```
+
+### Directory Structure
+
+```plaintext
+display-outputs/
+├── index.tsx    # Component main entry, implements DisplayOutputs component
+└── styles.css   # Component styles
+```
+
+### Core Implementation
+
+Core logic of the DisplayOutputs component:
+
+1. **Scope Mode** (`displayFromScope=true`): Uses `useCurrentScope` Hook to get output variables from current scope, converts variable list to JSON Schema properties through `scope?.output.variables`
+
+2. **Field Mode** (`displayFromScope=false`): Directly uses JSON Schema object passed through `value` prop
+
+3. **Variable Listening**: In scope mode, component listens for output variable changes and automatically refreshes display
+
+4. **Rendering Implementation**: Renders each property of JSON Schema as `DisplaySchemaTag` component, supporting type icons and warning state display
+
+### Dependencies
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- [`useCurrentScope`](https://flowgram.ai/auto-docs/editor/functions/useCurrentScope): Hook to get current scope
+- [`useRefresh`](https://flowgram.ai/api/hooks/use-refresh): Hook to force component refresh
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/common/json-schema)
+- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema type definition
+- [`JsonSchemaUtils`](https://flowgram.ai/auto-docs/json-schema/modules/JsonSchemaUtils): JSON Schema utility functions
+- [`JsonSchemaTypeManager`](https://flowgram.ai/auto-docs/json-schema/classes/JsonSchemaTypeManager): Type manager
+
+#### Other Materials
+
+[**DisplaySchemaTag**](./display-schema-tag)
+- `DisplaySchemaTag`: Tag component for displaying individual JSON Schema properties
+
+#### Third-party Libraries
+
+[**React**](https://react.dev/)
+- `useLayoutEffect`: Used for listening to scope variable changes

+ 157 - 3
apps/docs/src/en/materials/form-plugins/infer-assign-plugin.mdx

@@ -1,11 +1,165 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/form-plugins/infer-assign-plugin';
+
+# inferAssignPlugin
+
+`inferAssignPlugin` is a form plugin used for variable assignment nodes to automatically derive output variables. It is typically used in conjunction with the [`AssignRows`](../components/assign-rows) component.
+
+The plugin implements the following capabilities for `declare` (declaring new variables) in `AssignRows`:
+- Automatically generates node output variables, where the variable name is the left-hand value in the `declare` operator, and the variable type is automatically inferred based on the `right` value.
+- When submitting data to the backend, automatically generates the corresponding JSON Schema based on the output variable types.
+
+## Examples
+
+### Basic Usage
+
+:::tip
+
+Click the Debug panel in the top right corner of the demo to view the JSON data sent to the backend
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
 :::
 
-# inferAssignPlugin (WIP)
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { createInferAssignPlugin, AssignRows, DisplayOutputs } from '@flowgram.ai/form-materials';
+
+export const VariableFormRender = ({ form }) => {
+  return (
+    <>
+      <FormHeader />
+      <AssignRows
+        name="assign"
+        defaultValue={[
+          // Declare variable from constant
+          {
+            operator: 'declare',
+            left: 'userName',
+            right: {
+              type: 'constant',
+              content: 'John Doe',
+              schema: { type: 'string' },
+            },
+          },
+          // Declare variable from variable
+          {
+            operator: 'declare',
+            left: 'userInfo',
+            right: {
+              type: 'ref',
+              content: ['start_0', 'obj'],
+            },
+          },
+          // Assign existing variable
+          {
+            operator: 'assign',
+            left: {
+              type: 'ref',
+              content: ['start_0', 'str'],
+            },
+            right: {
+              type: 'constant',
+              content: 'Hello Flowgram',
+              schema: { type: 'string' },
+            },
+          },
+        ]}
+      />
+      <DisplayOutputs displayFromScope />
+    </>
+  );
+};
+
+export const formMeta: FormMeta = {
+  render: VariableFormRender,
+  plugins: [
+    createInferAssignPlugin({
+      assignKey: 'assign',
+      outputKey: 'outputs'
+    })
+  ],
+};
+```
+
+## API Reference
+
+```typescript
+function createInferAssignPlugin(options: {
+  assignKey: string;
+  outputKey: string;
+}): FormPlugin;
+```
+
+| Property | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| assignKey | `string` | - | Field path in the form for storing the assignment operations array, value type is `AssignValueType[]` |
+| outputKey | `string` | - | Field path for storing the output JSON Schema |
+
+
+## Source Code Guide
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/form-plugins/infer-assign-plugin"
 />
+
+You can copy the source code locally using the CLI command:
+
+```bash
+npx @flowgram.ai/cli@latest materials form-plugins/infer-assign-plugin
+```
+
+### Directory Structure
+
+```plaintext
+infer-assign-plugin/
+└── index.ts                  # Main plugin entry, creates and exports the plugin
+```
+
+### Core Implementation
+
+
+```mermaid
+sequenceDiagram
+    participant Form as Form
+    participant Plugin as inferAssignPlugin
+    participant Provider as VariableProvider
+    participant Scope as Variable Scope
+    participant Runtime as Backend Runtime
+
+    Form->>Plugin: onSetupFormMeta()
+    Plugin->>Form: Register variable provision side effects
+
+    loop Iterate through each assignment operation
+        alt operator = 'declare'
+          Plugin->>Plugin: Generate variable declaration (left -> VariableDeclaration)
+        end
+    end
+
+    Plugin->>Provider: Provide variables to scope
+    Provider->>Scope: Register output variables
+    Plugin-->>Runtime: Derive output variable JSON Schema
+
+```
+
+### Dependencies
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- `defineFormPluginCreator`: Factory function for defining form plugins
+- `FormPlugin`: Form plugin type definition
+- `FormPluginSetupMetaCtx`: Plugin setup context, provides `mergeEffect`, `addFormatOnSubmit` methods
+
+[**@flowgram.ai/variable-core**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/variable-core)
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/json-schema)
+- `IJsonSchema`: JSON Schema type definition
+
+#### Other Dependencies
+
+[**FlowValue**](../common/flow-value)
+- `FlowValueUtils.inferJsonSchema()`: Infers JSON Schema from IFlowValue
+- `FlowValueUtils.isConstant()`, `FlowValueUtils.isRef()`: Type checking utilities
+- `IFlowValue`: Union type for Flow values
+- `IFlowRefValue`: Variable reference type
+- `IFlowConstantValue`: Constant type

+ 188 - 5
apps/docs/src/en/materials/form-plugins/infer-inputs-plugin.mdx

@@ -1,11 +1,194 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/form-plugins/infer-inputs-plugin';
+
+# inferInputsPlugin
+
+`inferInputsPlugin` is a **form plugin for automatically inferring JSON Schema of input parameters**. It can **automatically generate corresponding JSON Schema structures based on IFlowValue types (constants or variable references) before data is sent to the backend runtime**, providing type information for backend runtime type validation and backend interfaces.
+
+<br />
+<div>
+  <img loading="lazy" src="/materials/infer-inputs-plugin.png" alt="Schema Inference" style={{ width: '75%' }} />
+  *When transmitted to the backend runtime, the JSON Schema of the inputs field is inferred from the values in inputsValues*
+</div>
+
+:::tip{title="Applicable Scenarios"}
+
+- **HTTP Nodes**: Infer Schema for request headers and query parameters
+- **Code Nodes**: Infer type structure for code input parameters
+- **Function Call Nodes**: Infer Schema for function parameters
+- **Any nodes accepting dynamic inputs**: Need to provide input type information for the backend
+
+:::
+
+## Demo
+
+### Basic Usage
+
+:::tip
+
+Click the Debug panel in the top right corner of the demo to view the JSON data sent to the backend
 
-:::warning
-The material has been developed and the documentation is still being improved. Contributions are welcome.
 :::
 
-# inferInputsPlugin (WIP)
+<BasicStory />
+
+Infer Schema for HTTP request headers and body:
+
+```tsx pure title="form-meta.tsx"
+import { createInferInputsPlugin, InputsValue, InputsValuesTree } from '@flowgram.ai/form-materials';
+import { Field } from '@flowgram.ai/editor';
+
+export const HttpFormRender = ({ form }) => {
+  return (
+    <>
+      <FormHeader />
+      <FormContent>
+        <Field<Record<string, IFlowValue>> name="headersValues">
+          {({ field }) => (
+            <InputsValues
+              value={field.value}
+              onChange={(val) => field.onChange(val)}
+            />
+          )}
+        </Field>
+        <Field<Record<string, IFlowValue>> name="bodyValues">
+          {({ field }) => (
+            <InputsValuesTree
+              value={field.value}
+              onChange={(val) => field.onChange(val)}
+            />
+          )}
+        </Field>
+      </FormContent>
+    </>
+  );
+};
+
+export const formMeta: FormMeta = {
+  render: HttpFormRender,
+  plugins: [
+    // Infer Schema for headers
+    createInferInputsPlugin({
+      sourceKey: 'headersValues',
+      targetKey: 'headersSchema'
+    }),
+    // Infer Schema for body
+    createInferInputsPlugin({
+      sourceKey: 'bodyValues',
+      targetKey: 'bodySchema'
+    })
+  ],
+};
+```
+
+## API Reference
+
+```typescript
+function createInferInputsPlugin(options: {
+  sourceKey: string;
+  targetKey: string;
+  scope?: 'private' | 'public';
+  ignoreConstantSchema?: boolean;
+}): FormPlugin;
+```
+
+| Property | Type | Default | Description |
+| :--- | :--- | :--- | :--- |
+| sourceKey | `string` | - | Field path in the form that stores input values, value type is an object or array containing IFlowValue |
+| targetKey | `string` | - | Field path where the inferred JSON Schema is stored |
+| scope | `'private' \| 'public'` | `public` | Specifies the scope type used for variable resolution |
+| ignoreConstantSchema | `boolean` | `false` | Whether to strip the Schema of constant values during submission (only keep Schema of variable references) |
+
+## Source Code Guide
 
 <SourceCode
-  href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/form-plugins/infer-inputs-plugin"
-/>
+  href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/form-plugins/infer-inputs-plugin/index.ts"
+/>
+
+Use CLI command to copy source code locally:
+
+```bash
+npx @flowgram.ai/cli@latest materials form-plugins/infer-inputs-plugin
+```
+
+### Directory Structure
+
+```plaintext
+infer-inputs-plugin/
+└── index.tsx  # Complete plugin implementation, including Schema inference and bidirectional conversion logic
+```
+
+### Core Implementation
+
+The core function of `inferInputsPlugin` is to infer JSON Schema from IFlowValue objects. For constant values, it directly uses their `schema` field; for variable references, it queries variable types from the scope; for expressions and templates, it infers them as corresponding basic types. The plugin also supports `ignoreConstantSchema` optimization, stripping constant Schema during submission and automatically restoring it during initialization.
+
+#### Workflow Sequence Diagram
+
+```mermaid
+sequenceDiagram
+    participant Form as Form
+    participant Plugin as inferInputsPlugin
+    participant Scope as Variable Scope
+    participant Backend as Backend
+
+    Note over Form: Form Submission
+    Form->>Plugin: onSubmit triggered
+    Plugin->>Plugin: Read sourceKey data
+
+    loop Iterate each IFlowValue
+        alt Type is constant
+            Plugin->>Plugin: Use value.schema
+            opt ignoreConstantSchema = true
+                Plugin->>Plugin: Strip schema
+            end
+        else Type is ref
+            Plugin->>Scope: Query variable type
+            Scope->>Plugin: Return variable Schema
+        else Type is expression/template
+            Plugin->>Plugin: Infer as any/string type
+        end
+    end
+
+    Plugin->>Plugin: Merge all Schemas
+    Plugin->>Form: Set to targetKey
+    Form->>Backend: Submit data containing Schema
+
+    Note over Form: Form Initialization
+    Backend->>Form: Return data (may lack constant Schema)
+    Form->>Plugin: onInit triggered
+    opt ignoreConstantSchema = true
+        Plugin->>Plugin: Restore constant Schema from sourceKey
+        Plugin->>Form: Update targetKey
+    end
+```
+
+Core Features:
+
+1. **Automatic Schema Inference**: Scans IFlowValue objects in form data and automatically infers their JSON Schema
+2. **Variable Type Resolution**: For variable references, resolves the actual type of variables from the scope
+3. **Constant Schema Optimization**: Optionally strips constant Schema during submission to reduce backend data load
+4. **Bidirectional Conversion**: Restores Schema during form initialization and generates Schema during form submission
+
+### Dependencies
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- `defineFormPluginCreator`: Factory function for defining form plugins
+- `FormPlugin`: Form plugin type definition
+- `FormPluginSetupMetaCtx`: Plugin setup context, provides `addFormatOnInit`, `addFormatOnSubmit` methods
+
+[**@flowgram.ai/variable-core**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/variable-core)
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/json-schema)
+- `IJsonSchema`: JSON Schema type definition
+
+#### Other Dependencies
+
+[**FlowValue**](../common/flow-value)
+- `FlowValueUtils.inferJsonSchema()`: Infer JSON Schema of IFlowValue
+- `FlowValueUtils.traverse()`: Traverse nested FlowValue structures
+- `FlowValueUtils.isConstant()`, `FlowValueUtils.isRef()`: Type judgment tools
+- `IFlowValue`: Union type of Flow values
+- `IFlowConstantValue`: Constant type, contains `schema` field
+- `IFlowRefValue`: Variable reference type, contains variable path

+ 157 - 4
apps/docs/src/zh/materials/components/assign-row.mdx

@@ -1,11 +1,164 @@
 import { SourceCode } from '@theme';
+import { AssignModeStory, DeclareModeStory } from 'components/form-materials/components/assign-row';
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
-:::
+# AssignRow
 
-# AssignRow (WIP)
+AssignRow 是一个赋值行组件,支持两种操作模式:**赋值模式 (assign)** 和 **声明模式 (declare)**。
+
+- 在赋值模式下:左侧是变量选择器,右侧是动态值输入;
+- 在声明模式下:左侧是文本输入框,右侧是动态值输入。
+
+## 案例演示
+
+### 赋值模式
+
+AssignRow **默认为赋值模式**,在赋值模式下,左侧为变量选择器,右侧为动态值输入:
+
+<AssignModeStory />
+
+```tsx pure title="form-meta.tsx"
+import { AssignRow } from '@flowgram.ai/form-materials';
+import { AssignValueType } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<AssignValueType | undefined> name="assign_row">
+        {({ field }) => (
+          <AssignRow value={field.value} onChange={(value) => field.onChange(value)} />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+### 声明模式
+
+声明模式下,左侧为变量名输入,右侧为动态值输入:
+
+<DeclareModeStory />
+
+```tsx pure title="form-meta.tsx"
+import { AssignRow } from '@flowgram.ai/form-materials';
+import { AssignValueType } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<AssignValueType | undefined> name="assign_row">
+        {({ field }) => (
+          <AssignRow
+            value={{
+              operator: 'declare',
+              left: 'newVariable',
+              right: {
+                type: 'constant',
+                content: 'Hello World',
+                schema: { type: 'string' },
+              },
+            }}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+
+
+## API 参考
+
+### AssignRow Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `value` | `AssignValueType` | - | 赋值行的值,包含操作符、左侧值和右侧值 |
+| `onChange` | `(value?: AssignValueType) => void` | - | 值变化时的回调函数 |
+| `onDelete` | `() => void` | - | 删除按钮点击时的回调函数 |
+| `readonly` | `boolean` | `false` | 是否为只读模式 |
+
+### AssignValueType
+
+```typescript
+type AssignValueType =
+  | {
+      operator: 'assign';
+      left?: IFlowRefValue;      // 变量引用
+      right?: IFlowValue;        // 动态值
+    }
+  | {
+      operator: 'declare';
+      left?: string;             // 变量名
+      right?: IFlowValue;        // 动态值
+    };
+```
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/assign-row"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/assign-row
+```
+
+### 目录结构讲解
+
+```
+assign-row/
+├── index.tsx     # AssignRow 组件主实现
+└── types.ts      # 类型定义文件
+```
+
+### 核心实现说明
+
+AssignRow 组件的核心逻辑是根据 `operator` 字段来渲染不同的左侧输入控件:
+
+1. **赋值模式 (`operator: 'assign'`)**:左侧渲染 `InjectVariableSelector`,用于选择已有变量
+2. **声明模式 (`operator: 'declare'`)**:左侧渲染 `BlurInput`,用于输入新变量名
+3. **右侧统一**:无论哪种模式,右侧都渲染 `InjectDynamicValueInput`,支持常量和变量输入
+
+#### 组件结构
+
+```mermaid
+graph TD
+    A[AssignRow 组件] --> B{判断 operator 类型}
+    B -->|assign| C[渲染变量选择器]
+    B -->|declare| D[渲染文本输入框]
+
+    C --> E[右侧动态值输入]
+    D --> E
+
+    E --> F[可选的删除按钮]
+
+    C --> G[支持 onDelete 回调]
+    D --> G
+    F --> G
+```
+
+### 依赖梳理
+
+#### 其他物料
+
+[**VariableSelector**](./variable-selector)
+- `InjectVariableSelector`: 依赖注入的变量选择器
+
+[**DynamicValueInput**](./dynamic-value-input)
+- `InjectDynamicValueInput`: 依赖注入的动态值输入组件
+
+[**BlurInput**](./blur-input)
+- `BlurInput`: 失焦输入组件
+
+#### 第三方库
+
+[**Semi Design**](https://semi.design/zh-CN/)
+- `IconButton`: 图标按钮组件
+- `IconMinus`: 减号图标

+ 107 - 3
apps/docs/src/zh/materials/components/assign-rows.mdx

@@ -1,11 +1,115 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/components/assign-rows';
+
+# AssignRows
+
+AssignRows 是一个赋值行列表组件,基于 `FieldArray` 实现,支持动态添加和删除赋值行。
+
+组件提供了两个操作按钮:**赋值** 和 **声明**,可以分别添加赋值模式和声明模式的赋值行。每个赋值行都可以独立配置和删除。
+
+:::tip
+
+`AssignRows` 通常和 [`infer-assign-plugin`](../form-plugins/infer-assign-plugin) 表单插件一起使用,用于将定义的声明转换为节点的输出变量,并实现类型的自动联动。
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
 :::
 
-# AssignRows (WIP)
+## 案例演示
+
+### 基本使用
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { AssignRows } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <AssignRows name="assign_rows" />
+    </>
+  ),
+}
+```
+
+
+
+## API 参考
+
+### AssignRows Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `name` | `string` | - | 表单字段名称,用于 FieldArray |
+| `readonly` | `boolean` | `false` | 是否为只读模式 |
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/assign-rows"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/assign-rows
+```
+
+### 目录结构讲解
+
+```
+assign-rows/
+└── index.tsx     # AssignRows 组件主实现
+```
+
+### 核心实现说明
+
+AssignRows 组件的核心功能是基于 `FieldArray` 实现的动态列表管理:
+
+1. **动态添加**:提供两个按钮分别添加赋值模式和声明模式的行
+2. **动态删除**:每行都支持独立的删除操作
+3. **状态管理**:使用 `FieldArray` 管理整个列表的状态
+4. **组件复用**:每行都复用 `AssignRow` 组件
+
+#### 组件工作流程
+
+```mermaid
+graph TD
+    A[AssignRows 组件] --> B[FieldArray 包装]
+    B --> C[渲染现有行列表]
+    C --> D[每行使用 AssignRow]
+    D --> E[支持 onChange 和 onDelete]
+
+    B --> F[添加按钮区域]
+    F --> G[赋值按钮]
+    F --> H[声明按钮]
+
+    G --> I[添加赋值行]
+    H --> J[添加声明行]
+
+    I --> K[调用 field.append]
+    J --> K
+
+    E --> L[调用 field.remove]
+```
+
+### 依赖梳理
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- `FieldArray`: 表单数组字段组件,用于管理动态列表
+- `FieldArrayRenderProps`: FieldArray 渲染属性类型
+
+#### 其他物料
+
+[**AssignRow**](./assign-row)
+- `AssignRow`: 赋值行组件,处理单行逻辑
+- `AssignValueType`: 赋值行值类型定义
+
+#### 第三方库
+
+[**Semi Design**](https://semi.design/zh-CN/)
+- `Button`: 按钮组件
+- `IconPlus`: 加号图标
+

+ 200 - 2
apps/docs/src/zh/materials/components/batch-variable-selector.mdx

@@ -1,11 +1,209 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/components/batch-variable-selector';
+
+# BatchVariableSelector
+
+BatchVariableSelector 是一个用于选择数组类型变量的组件,它是 [VariableSelector](./variable-selector) 的封装版本。
+
+该组件自动过滤变量树,只显示数组类型的变量,并自动设定[私有作用域](../../guide/variable/concept#节点私有作用域),常用于批处理场景(如 Loop 节点的循环数据源选择)。
+
+**核心特性:**
+
+- 🔍 **自动过滤**:只显示数组类型(`type: 'array'`)的变量。
+- 🔐 **私有作用域**:通过 [`PrivateScopeProvider`](../../guide/variable/concept#节点私有作用域) 提供独立的变量作用域。
+- 🎯 **专用场景**:专为批处理、循环等需要数组数据源的场景设计。
+
+## 案例演示
+
+### 基本使用
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { BatchVariableSelector, VariableSelector } from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      {/* BatchVariableSelector 只显示数组类型变量 */}
+      <Field<string[] | undefined> name="batch_variable">
+        {({ field }) => (
+          <BatchVariableSelector
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+
+      {/* VariableSelector 显示所有类型变量 */}
+      <Field<string[] | undefined> name="normal_variable">
+        {({ field }) => (
+          <VariableSelector
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API 参考
+
+### BatchVariableSelector Props
+
+BatchVariableSelector 继承了 [VariableSelector](./variable-selector) 的所有属性,但 `includeSchema` 属性已被固定为数组类型过滤,无法自定义。
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `value` | `string[]` | - | 选中的变量路径数组 |
+| `onChange` | `(value?: string[]) => void` | - | 变量选择变化时的回调函数 |
+| `config` | `VariableSelectorConfig` | `{}` | 配置对象(同 VariableSelector) |
+| `readonly` | `boolean` | `false` | 是否为只读模式 |
+| `hasError` | `boolean` | `false` | 是否显示错误状态 |
+| `style` | `React.CSSProperties` | - | 自定义样式 |
+| `triggerRender` | `(props: TriggerRenderProps) => React.ReactNode` | - | 自定义触发器渲染 |
 
 :::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
+`includeSchema` 和 `excludeSchema` 属性在 BatchVariableSelector 中不可用,因为组件内部已固定使用 `{ type: 'array', extra: { weak: true } }` 作为过滤条件。
 :::
 
-# BatchVariableSelector (WIP)
+### VariableSelectorConfig
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `placeholder` | `string` | `'选择变量'` | 占位符文本 |
+| `notFoundContent` | `string` | `'未定义'` | 变量未找到时的显示内容 |
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/batch-variable-selector"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/batch-variable-selector
+```
+
+### 目录结构讲解
+
+```
+batch-variable-selector/
+└── index.tsx           # 主组件实现,包含 BatchVariableSelector 核心逻辑
+```
+
+### 核心实现说明
+
+#### 私有作用域机制
+
+BatchVariableSelector 通过 `PrivateScopeProvider` 为子组件提供独立的变量作用域:
+
+```tsx
+<PrivateScopeProvider>
+  <VariableSelector {...props} includeSchema={batchVariableSchema} />
+</PrivateScopeProvider>
+```
+
+`PrivateScopeProvider` 会创建一个[节点私有作用域](../../guide/variable/concept#节点私有作用域),这在批处理场景中非常重要:
+
+- **循环变量隔离**:在 Loop 节点中,每次迭代的循环变量(如 `item`、`index`)都存储在私有作用域中,避免污染外部作用域
+- **避免命名冲突**:批处理节点内部定义的临时变量不会与外部变量产生命名冲突
+- **支持嵌套结构**:复杂的批处理逻辑可以在私有作用域中定义多层变量结构
+- **数据安全**:私有作用域中的变量只能被当前节点及其子节点访问,确保数据安全性
+
+:::info
+
+更多关于作用域的详细信息,请参考[变量概念文档](../../guide/variable/concept#画布中的变量)。
+
+:::
+
+#### 数组类型过滤
+
+组件内部固定使用以下 schema 进行过滤:
+
+```typescript
+const batchVariableSchema: IJsonSchema = {
+  type: 'array',
+  extra: { weak: true },
+};
+```
+
+- `type: 'array'`:只显示数组类型的变量
+- `extra: { weak: true }`:启用弱类型匹配,允许匹配可能兼容的类型
+
+### 整体流程
+
+```mermaid
+sequenceDiagram
+    participant User
+    participant BatchVariableSelector
+    participant PrivateScopeProvider
+    participant VariableSelector
+    participant useVariableTree
+    participant VariableTree
+
+    User->>BatchVariableSelector: 选择数组变量
+    BatchVariableSelector->>PrivateScopeProvider: 设定私有作用域上下文
+    PrivateScopeProvider->>VariableSelector: 传递包含数组过滤的 schema
+    VariableSelector->>useVariableTree: 获取可用变量列表
+    useVariableTree->>VariableTree: 查询变量树数据
+    VariableTree-->>useVariableTree: 返回所有变量
+    useVariableTree-->>VariableSelector: 过滤出数组类型变量
+    VariableSelector-->>BatchVariableSelector: 渲染数组变量选择器
+    BatchVariableSelector-->>User: 显示可选的数组变量
+```
+
+### 使用到的 FlowGram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/plugins/node-variable-plugin)
+- [`PrivateScopeProvider`](https://flowgram.ai/auto-docs/node-variable-plugin/functions/PrivateScopeProvider): 提供私有变量作用域的 Context Provider
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable/json-schema)
+- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema 类型定义,用于变量类型过滤
+
+### 依赖的其他物料
+
+[**VariableSelector**](./variable-selector) 变量选择器基础组件
+- `VariableSelector`: 核心变量选择组件,BatchVariableSelector 是其封装版本
+- `VariableSelectorProps`: 属性类型定义
+
+## 常见问题
+
+### 为什么需要 PrivateScopeProvider?
+
+`PrivateScopeProvider` 提供了变量作用域隔离机制,在以下场景中非常重要:
+
+1. **循环节点**:在 Loop 节点中,每次迭代都需要一个独立的作用域来存储循环变量(如 `item`, `index`)。参考[变量概念 - 节点私有作用域](../../guide/variable/concept#节点私有作用域)
+2. **嵌套结构**:当节点内部有嵌套的变量声明时,避免与外部变量产生命名冲突
+3. **组件复用**:相同的组件在不同上下文中使用时,确保变量不会互相干扰
+4. **数据安全**:私有作用域中的变量只能被当前节点及其子节点访问,确保数据安全性
+
+更多关于作用域链和变量访问权限的信息,请参考[变量概念 - 作用域链](../../guide/variable/concept#作用域链)。
+
+### BatchVariableSelector 与 VariableSelector 的区别?
+
+| 特性 | BatchVariableSelector | VariableSelector |
+|------|----------------------|------------------|
+| 变量类型过滤 | 固定为数组类型 | 可自定义 |
+| 作用域 | 自带私有作用域 | 使用当前作用域 |
+| 使用场景 | 批处理、循环等 | 通用变量选择 |
+| Schema 配置 | 不可配置 | 完全可配置 |
+
+### 如何获取选中变量的实际值?
+
+BatchVariableSelector 返回的是变量路径(`string[]`),如需获取实际值,需要在表单的 effect 中配合 [`provideBatchInputEffect`](../effects/provide-batch-input) 使用:
+
+```typescript
+export const formMeta = {
+  render: YourFormRender,
+  effect: {
+    yourFieldName: provideBatchInputEffect,
+  },
+};
+```
+
+`provideBatchInputEffect` 会自动解析变量引用并注入到表单数据中。

+ 169 - 3
apps/docs/src/zh/materials/components/constant-input.mdx

@@ -1,11 +1,177 @@
 import { SourceCode } from '@theme';
+import { BasicStory, FallbackRendererStory, CustomStrategyStory } from 'components/form-materials/components/constant-inputs';
+
+# ConstantInput
+
+ConstantInput 是一个常量输入组件,它根据提供的 JSON Schema 自动选择合适的输入类型渲染器。
+
+组件支持自定义渲染策略和兜底渲染器,能够处理各种数据类型的常量输入。
+
+## 案例演示
+
+### 基本使用
+
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<string> name="constant_string" defaultValue="Hello World">
+        {({ field }) => (
+          <ConstantInput
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'string' }}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+:::tip{title="注册新类型的常量输入器"}
+
+参考 [类型管理](../common/json-schema-preset),在类型注册的时候为类型配置常量输入器
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
 :::
 
-# ConstantInput (WIP)
+### 兜底渲染器
+
+当组件无法找到合适的渲染器时,会使用兜底渲染器:
+
+<FallbackRendererStory />
+
+```tsx pure title="form-meta.tsx"
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<any> name="constant_fallback" defaultValue={{ custom: 'data' }}>
+        {({ field }) => (
+          <ConstantInput
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'custom-unsupported-type' }}
+            fallbackRenderer={({ value, onChange, readonly }) => (
+              <div style={{ padding: '8px', background: '#f0f0f0', border: '1px dashed #ccc' }}>
+                <p>Fallback renderer for unsupported type</p>
+              </div>
+            )}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+### 自定义策略
+
+使用自定义渲染策略来覆盖默认行为:
+
+<CustomStrategyStory />
+
+```tsx pure title="form-meta.tsx"
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<string> name="constant_custom" defaultValue="自定义值">
+        {({ field }) => (
+          <ConstantInput
+            value={field.value}
+            onChange={(value) => field.onChange(value)}
+            schema={{ type: 'object' }}
+            strategies={[
+              {
+                hit: (schema) => schema.type === 'object',
+                Renderer: ({ value, onChange, readonly }) => (
+                  <p>Object is not supported now</p>
+                ),
+              },
+            ]}
+          />
+        )}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API 参考
+
+### ConstantInput Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `value` | `any` | - | 输入值 |
+| `onChange` | `(value: any) => void` | - | 值变化时的回调函数 |
+| `schema` | `IJsonSchema` | - | 用于确定渲染器的 JSON Schema |
+| `strategies` | `Strategy[]` | - | 自定义渲染策略数组 |
+| `fallbackRenderer` | `React.FC<ConstantRendererProps>` | - | 当没有合适渲染器时使用的兜底渲染器 |
+| `readonly` | `boolean` | `false` | 是否为只读模式 |
+
+### Strategy 接口
+
+```typescript
+interface Strategy<Value = any> {
+  hit: (schema: IJsonSchema) => boolean;
+  Renderer: React.FC<ConstantRendererProps<Value>>;
+}
+```
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/constant-input"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/constant-input
+```
+
+### 目录结构讲解
+
+```
+constant-input/
+├── index.tsx    # 主组件实现,包含 ConstantInput 核心逻辑
+└── types.ts     # 类型定义,包括 Strategy 接口和 PropsType
+```
+
+### 核心实现说明
+
+#### 渲染器选择逻辑
+
+组件通过以下步骤选择合适的渲染器:
+
+1. **策略匹配**:首先检查 `strategies` 数组中是否有匹配当前 schema 的策略
+2. **类型管理器**:如果没有匹配的策略,则使用类型管理器 (`useTypeManager`) 获取对应 schema 的渲染器
+3. **兜底渲染**:如果以上都失败,使用提供的 `fallbackRenderer` 或默认的禁用输入框
+
+
+#### 类型系统集成
+
+ConstantInput 与 [**物料类型管理**](../common/json-schema-preset) 深度集成:
+
+- 通过 `useTypeManager` Hook 获取类型管理器
+- 使用 `typeManager.getTypeBySchema(schema)` 获取对应类型的渲染器
+- 支持所有 JSON Schema 标准类型(string, number, boolean, object, array 等)
+
+### 依赖梳理
+
+#### flowgram API
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable/json-schema)
+- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema 类型定义
+- [`useTypeManager`](https://flowgram.ai/auto-docs/json-schema/functions/useTypeManager): 类型管理器 Hook
+
+#### 第三方库
+
+[**Semi UI**](https://semi.design/zh-CN)
+- 基础输入组件库,提供默认的输入控件
+

+ 155 - 3
apps/docs/src/zh/materials/components/coze-editor-extensions.mdx

@@ -1,11 +1,163 @@
 import { SourceCode } from '@theme';
+import { BasicStory as PromptWithVariablesStory } from 'components/form-materials/components/prompt-editor-with-variables';
+import { BasicStory as PromptWithInputsStory } from 'components/form-materials/components/prompt-editor-with-inputs';
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
+# CozeEditorExtensions
+
+CozeEditorExtensions 是一组基于 [coze-editor](https://github.com/coze-dev/rush-arch/tree/main/packages/text-editor) 的功能扩展,提供变量、Inputs 选择器与变量标签回显能力。
+
+- `EditorVariableTree`:监听 `@`/`{` 等触发字符,弹出可用变量树并将选中项写入编辑器。
+- `EditorVariableTagInject`:对 `{{variable.path}}` 文本进行标记渲染,展示变量图标、标题与回显提示。
+- `EditorInputsTree`:基于节点 `inputsValues` 构造层级树,支持在提示词中插入 `{{inputs.xxx}}` 引用。
+
+## 案例演示
+
+### 变量树 + 标签回显
+
+<PromptWithVariablesStory />
+
+```tsx pure title="prompt-editor-with-extensions.tsx"
+import {
+  PromptEditor,
+  EditorVariableTree,
+  EditorVariableTagInject,
+  EditorInputsTree,
+} from '@flowgram.ai/form-materials';
+
+const formMeta = {
+  render: () => (
+    <PromptEditor value={value} onChange={onChange}>
+      <EditorVariableTree triggerCharacters={TRIGGER_CHARACTERS} />
+      <EditorVariableTagInject />
+    </PromptEditor>
+  );
+}
+```
+
+:::tip{title="触发方式"}
+`EditorVariableTree` 默认监听 `{`、`{{` 和 `@`,你可以通过 `triggerCharacters` 自定义触发字符。
 :::
 
-# CozeEditorExtensions (WIP)
+### 节点 Inputs 引用
+
+<PromptWithInputsStory />
+
+
+```tsx pure title="prompt-editor-with-extensions.tsx"
+import {
+  PromptEditor,
+  EditorVariableTree,
+  EditorVariableTagInject,
+  EditorInputsTree,
+} from '@flowgram.ai/form-materials';
+
+
+export function PromptEditorWithExtensions({ value, onChange, inputsValues }) {
+  return (
+    <PromptEditor value={value} onChange={onChange}>
+      <EditorInputsTree inputsValues={inputsValues} />
+    </PromptEditor>
+  );
+}
+```
+
+
+### 渲染键与二次扩展
+
+CozeEditorExtensions 通过 [`createInjectMaterial`](../common/inject-material) 声明了固定的 `renderKey`:
+
+- `EditorVariableTree.renderKey = 'EditorVariableTree'`
+- `EditorVariableTagInject.renderKey = 'EditorVariableTagInject'`
+- `EditorInputsTree.renderKey = 'EditorInputsTree'`
+
+你可以在 `use-editor-props` 中注册同名渲染器,以替换默认行为。例如自定义变量选择面板:
+
+```tsx pure title="override-variable-tree.tsx"
+import { useEditorProps } from '@flowgram.ai/editor';
+import { EditorVariableTree } from '@flowgram.ai/form-materials';
+import { CustomVariableTree } from './custom-variable-tree';
+
+export function useCustomEditorProps() {
+  return useEditorProps({
+    materials: {
+      components: {
+        [EditorVariableTree.renderKey!]: CustomVariableTree,
+      },
+    },
+  });
+}
+```
+
+
+## API 参考
+
+### EditorVariableTree Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `triggerCharacters` | `string[]` | `['{', '{}', '@']` | 触发变量树弹出的字符集 |
+
+### EditorVariableTagInject Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| _无_ | - | - | 组件无额外属性,渲染即生效 |
+
+### EditorInputsTree Props
+
+| 属性名 | 类型 | 默认值 | 描述 |
+|--------|------|--------|------|
+| `inputsValues` | `IInputsValues` | - | 节点 Inputs 的键值数据,支持 `FlowValue` 引用 |
+| `triggerCharacters` | `string[]` | `['{', '{}', '@']` | 触发 Inputs 选择器的字符集 |
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/coze-editor-extensions"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials components/coze-editor-extensions
+```
+
+### 目录结构讲解
+
+```
+coze-editor-extensions/
+├── index.tsx                 # 导出可注入物料
+├── extensions/
+│   ├── inputs-tree.tsx       # Inputs Tree 实现
+│   ├── variable-tag.tsx      # 变量标签渲染
+│   └── variable-tree.tsx     # 变量树选择器
+└── styles.css                # 标签样式与弹窗样式
+```
+
+### 核心实现说明
+
+**EditorVariableTree**
+- 弹窗定位与滚动同步:`Mention` + `PositionMirror` 组合确保 Popover 始终贴合光标位置,滚动时会通过 `rePosKey` 触发重新定位
+- 变量树数据来源:`useVariableTree` 读取 `Scope.available` 中注册的变量,自动应用 schema 过滤、禁用状态和图标
+
+**EditorVariableTagInject**
+- 标签渲染与订阅:使用 CodeMirror `MatchDecorator` 将 `{{xxx}}` 文本替换为 `Tag` 小部件,并订阅变量标题/Icon 更新,实现实时回显
+
+**EditorInputsTree**
+- Inputs 树构造:支持 `FlowValue` 与普通对象,递归生成层级节点,并在插入前统一格式化为 `{{path}}`
+
+### 依赖梳理
+
+#### 其他物料
+
+[**InjectMaterial**](../common/inject-material)
+- `createInjectMaterial`: 创建可注入的物料组件
+
+#### 第三方库
+
+[**coze-editor**](https://github.com/coze-dev/rush-arch/tree/main/packages/text-editor)
+- 基础编辑器组件
+
+[**CodeMirror MatchDecorator**](https://codemirror.net/docs/ref/#search.MatchDecorator)
+- 用于变量标签的文本匹配和替换
+

+ 125 - 4
apps/docs/src/zh/materials/components/display-outputs.mdx

@@ -1,11 +1,132 @@
 import { SourceCode } from '@theme';
+import { DisplayFromScopeStory, DisplayFromFieldStory } from 'components/form-materials/components/display-outputs';
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
-:::
+# DisplayOutputs
 
-# DisplayOutputs (WIP)
+DisplayOutputs 是一个用于可视化展示节点输出变量的组件,支持从作用域自动获取输出变量或通过字段值手动指定输出模式。
+
+## 案例演示
+
+### 从作用域获取输出变量
+
+当设置 `displayFromScope` 为 `true` 时,组件会自动从当前节点作用域获取输出变量并展示:
+
+<DisplayFromScopeStory />
+
+```tsx pure title="form-meta.tsx" {27}
+import { DisplayOutputs, provideJsonSchemaOutputs } from '@flowgram.ai/form-materials';
+import { Field } from '@flowgram.ai/editor';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<IJsonSchema | undefined> name="outputs">
+        {({ field }) => (
+          <JsonSchemaEditor value={field.value} onChange={(value) => field.onChange(value)} />
+        )}
+      </Field>
+      <p>Display Output Schema:</p>
+      <DisplayOutputs displayFromScope />
+    </>
+  ),
+  effect: {
+    outputs: provideJsonSchemaOutputs,
+  },
+}
+```
+
+### 通过字段值指定输出模式
+
+当不设置 `displayFromScope` 时,组件通过 `value` 属性接收输出的 JSON Schema:
+
+<DisplayFromFieldStory />
+
+```tsx pure title="form-meta.tsx"
+import { DisplayOutputs } from '@flowgram.ai/form-materials';
+import { Field } from '@flowgram.ai/editor';
+
+const formMeta = {
+  render: () => (
+    <>
+      <FormHeader />
+      <Field<IJsonSchema | undefined> name="outputs">
+        {({ field }) => (
+          <JsonSchemaEditor value={field.value} onChange={(value) => field.onChange(value)} />
+        )}
+      </Field>
+      <p>Display Output Schema:</p>
+      <Field<IJsonSchema | undefined> name="outputs">
+        {({ field }) => <DisplayOutputs value={field.value} />}
+      </Field>
+    </>
+  ),
+}
+```
+
+## API 参考
+
+### DisplayOutputs Props
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| :--- | :--- | :--- | :--- |
+| value | `IJsonSchema` | - | 要展示的 JSON Schema 对象,当 `displayFromScope` 为 `false` 时使用 |
+| displayFromScope | `boolean` | `false` | 是否从当前作用域自动获取输出变量 |
+| showIconInTree | `boolean` | `false` | 是否在树形结构中显示图标 |
+| typeManager | `JsonSchemaTypeManager` | - | 自定义类型管理器 |
+| style | `React.CSSProperties` | - | 自定义样式 |
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/components/display-outputs"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials display-outputs
+```
+
+### 目录结构讲解
+
+```plaintext
+display-outputs/
+├── index.tsx    # 组件主入口,实现 DisplayOutputs 组件
+└── styles.css   # 组件样式文件
+```
+
+### 核心实现说明
+
+DisplayOutputs 组件的核心逻辑:
+
+1. **作用域模式** (`displayFromScope=true`): 使用 `useCurrentScope` Hook 获取当前作用域的输出变量,通过 `scope?.output.variables` 获取变量列表并转换为 JSON Schema 属性
+
+2. **字段模式** (`displayFromScope=false`): 直接使用 `value` 属性传入的 JSON Schema 对象
+
+3. **变量监听**: 在作用域模式下,组件会监听输出变量的变化并自动刷新显示
+
+4. **渲染实现**: 将 JSON Schema 的每个属性渲染为 `DisplaySchemaTag` 组件,支持类型图标和警告状态显示
+
+### 依赖梳理
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- [`useCurrentScope`](https://flowgram.ai/auto-docs/editor/functions/useCurrentScope): 获取当前作用域的 Hook
+- [`useRefresh`](https://flowgram.ai/api/hooks/use-refresh): 强制组件刷新的 Hook
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/common/json-schema)
+- [`IJsonSchema`](https://flowgram.ai/auto-docs/json-schema/interfaces/IJsonSchema): JSON Schema 类型定义
+- [`JsonSchemaUtils`](https://flowgram.ai/auto-docs/json-schema/modules/JsonSchemaUtils): JSON Schema 工具函数
+- [`JsonSchemaTypeManager`](https://flowgram.ai/auto-docs/json-schema/classes/JsonSchemaTypeManager): 类型管理器
+
+#### 其他物料
+
+[**DisplaySchemaTag**](./display-schema-tag)
+- `DisplaySchemaTag`: 用于展示单个 JSON Schema 属性的标签组件
+
+#### 第三方库
+
+[**React**](https://react.dev/)
+- `useLayoutEffect`: 用于监听作用域变量变化

+ 157 - 3
apps/docs/src/zh/materials/form-plugins/infer-assign-plugin.mdx

@@ -1,11 +1,165 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/form-plugins/infer-assign-plugin';
+
+# inferAssignPlugin
+
+`inferAssignPlugin` 是用于变量赋值节点,进行输出变量自动推导的表单插件,通常和 [`AssignRows`](../components/assign-rows) 物料配合使用。
+
+插件针对 `AssignRows` 的 `declare` (声明新变量) 实现了以下能力:
+- 自动生成节点输出变量,变量名即 `declare` 操作符中的左值,变量类型会自动根据 `right` 进行联动推导。
+- 当提交数据到后端时,自动根据输出变量的变量类型,联动生成对应的 JSON Schema。
+
+## 案例演示
+
+### 基本使用
+
+:::tip
+
+点开 demo 右上角的 Debug 面板,查看传到后端的 JSON 数据
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
 :::
 
-# inferAssignPlugin (WIP)
+<BasicStory />
+
+```tsx pure title="form-meta.tsx"
+import { createInferAssignPlugin, AssignRows, DisplayOutputs } from '@flowgram.ai/form-materials';
+
+export const VariableFormRender = ({ form }) => {
+  return (
+    <>
+      <FormHeader />
+      <AssignRows
+        name="assign"
+        defaultValue={[
+          // 从常量声明变量
+          {
+            operator: 'declare',
+            left: 'userName',
+            right: {
+              type: 'constant',
+              content: 'John Doe',
+              schema: { type: 'string' },
+            },
+          },
+          // 从变量声明变量
+          {
+            operator: 'declare',
+            left: 'userInfo',
+            right: {
+              type: 'ref',
+              content: ['start_0', 'obj'],
+            },
+          },
+          // 赋值现有变量
+          {
+            operator: 'assign',
+            left: {
+              type: 'ref',
+              content: ['start_0', 'str'],
+            },
+            right: {
+              type: 'constant',
+              content: 'Hello Flowgram',
+              schema: { type: 'string' },
+            },
+          },
+        ]}
+      />
+      <DisplayOutputs displayFromScope />
+    </>
+  );
+};
+
+export const formMeta: FormMeta = {
+  render: VariableFormRender,
+  plugins: [
+    createInferAssignPlugin({
+      assignKey: 'assign',
+      outputKey: 'outputs'
+    })
+  ],
+};
+```
+
+## API 参考
+
+```typescript
+function createInferAssignPlugin(options: {
+  assignKey: string;
+  outputKey: string;
+}): FormPlugin;
+```
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| :--- | :--- | :--- | :--- |
+| assignKey | `string` | - | 表单中存储赋值操作数组的字段路径,值类型为 `AssignValueType[]` |
+| outputKey | `string` | - | 输出 JSON Schema 的存储位置字段路径 |
+
+
+## 源码导读
 
 <SourceCode
   href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/form-plugins/infer-assign-plugin"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials form-plugins/infer-assign-plugin
+```
+
+### 目录结构讲解
+
+```plaintext
+infer-assign-plugin/
+└── index.ts                  # 插件主入口,创建插件并导出
+```
+
+### 核心实现说明
+
+
+```mermaid
+sequenceDiagram
+    participant Form as 表单
+    participant Plugin as inferAssignPlugin
+    participant Provider as VariableProvider
+    participant Scope as 变量作用域
+    participant Runtime as 后端运行时
+
+    Form->>Plugin: onSetupFormMeta()
+    Plugin->>Form: 注册变量提供副作用
+
+    loop 遍历每个赋值操作
+        alt operator = 'declare'
+          Plugin->>Plugin: 生成变量声明 (left -> VariableDeclaration)
+        end
+    end
+
+    Plugin->>Provider: 提供变量到作用域
+    Provider->>Scope: 注册输出变量
+    Plugin-->>Runtime: 推导输出变量 JSON Schema
+
+```
+
+### 依赖梳理
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- `defineFormPluginCreator`: 定义表单插件的工厂函数
+- `FormPlugin`: 表单插件类型定义
+- `FormPluginSetupMetaCtx`: 插件设置上下文,提供 `mergeEffect`、`addFormatOnSubmit` 方法
+
+[**@flowgram.ai/variable-core**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/variable-core)
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/json-schema)
+- `IJsonSchema`: JSON Schema 类型定义
+
+#### 依赖的其他物料
+
+[**FlowValue**](../common/flow-value)
+- `FlowValueUtils.inferJsonSchema()`: 推断 IFlowValue 的 JSON Schema
+- `FlowValueUtils.isConstant()`, `FlowValueUtils.isRef()`: 类型判断工具
+- `IFlowValue`: Flow 值的联合类型
+- `IFlowRefValue`: 变量引用类型
+- `IFlowConstantValue`: 常量类型

+ 190 - 4
apps/docs/src/zh/materials/form-plugins/infer-inputs-plugin.mdx

@@ -1,11 +1,197 @@
 import { SourceCode } from '@theme';
+import { BasicStory } from 'components/form-materials/form-plugins/infer-inputs-plugin';
+
+# inferInputsPlugin
+
+`inferInputsPlugin`是一个用于**自动推断输入参数 JSON Schema 的表单插件**,它能**在数据传送到后端运行时前**,根据 IFlowValue 类型 (常量或变量引用) 自动生成对应的 JSON Schema 结构,为后端的运行时类型验证和后端接口提供类型信息。
+
+<br />
+<div>
+  <img loading="lazy" src="/materials/infer-inputs-plugin.png" alt="Schema 推断" style={{ width: '75%' }} />
+  *传到后端运行时时,inputs 字段的 JSON Schema 根据 inputsValues 中的值定义推导*
+</div>
+
+:::tip{title="适用场景"}
+
+- **HTTP 节点**:推断请求头 (headers)、查询参数 (params) 的 Schema
+- **代码节点**:推断代码输入参数的类型结构
+- **函数调用节点**:推断函数参数的 Schema
+- **任何接受动态输入的节点**:需要为后端提供输入类型信息
 
-:::warning
-物料已完成开发,文档还在完善中,欢迎参与贡献
 :::
 
-# inferInputsPlugin (WIP)
+## 案例演示
+
+### 基本使用
+
+
+### 基本使用
+
+:::tip
+
+点开 demo 右上角的 Debug 面板,查看传到后端的 JSON 数据
+
+:::
+
+<BasicStory />
+
+推断 HTTP 请求的 headers 和 body 的 Schema:
+
+```tsx pure title="form-meta.tsx"
+import { createInferInputsPlugin, InputsValue, InputsValuesTree } from '@flowgram.ai/form-materials';
+import { Field } from '@flowgram.ai/editor';
+
+export const HttpFormRender = ({ form }) => {
+  return (
+    <>
+      <FormHeader />
+      <FormContent>
+        <Field<Record<string, IFlowValue>> name="headersValues">
+          {({ field }) => (
+            <InputsValues
+              value={field.value}
+              onChange={(val) => field.onChange(val)}
+            />
+          )}
+        </Field>
+        <Field<Record<string, IFlowValue>> name="bodyValues">
+          {({ field }) => (
+            <InputsValuesTree
+              value={field.value}
+              onChange={(val) => field.onChange(val)}
+            />
+          )}
+        </Field>
+      </FormContent>
+    </>
+  );
+};
+
+export const formMeta: FormMeta = {
+  render: HttpFormRender,
+  plugins: [
+    // 推断 headers 的 Schema
+    createInferInputsPlugin({
+      sourceKey: 'headersValues',
+      targetKey: 'headersSchema'
+    }),
+    // 推断 body 的 Schema
+    createInferInputsPlugin({
+      sourceKey: 'bodyValues',
+      targetKey: 'bodySchema'
+    })
+  ],
+};
+```
+
+## API 参考
+
+```typescript
+function createInferInputsPlugin(options: {
+  sourceKey: string;
+  targetKey: string;
+  scope?: 'private' | 'public';
+  ignoreConstantSchema?: boolean;
+}): FormPlugin;
+```
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| :--- | :--- | :--- | :--- |
+| sourceKey | `string` | - | 表单中存储输入值的字段路径,值类型为包含 IFlowValue 的对象或数组 |
+| targetKey | `string` | - | 推断的 JSON Schema 存储位置的字段路径 |
+| scope | `'private' \| 'public'` | `public` | 指定用于变量解析的作用域类型 |
+| ignoreConstantSchema | `boolean` | `false` | 是否在提交时剥离常量值的 Schema(仅保留变量引用的 Schema) |
+
+## 源码导读
 
 <SourceCode
-  href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/form-plugins/infer-inputs-plugin"
+  href="https://github.com/bytedance/flowgram.ai/tree/main/packages/materials/form-materials/src/form-plugins/infer-inputs-plugin/index.ts"
 />
+
+使用 CLI 命令可以复制源代码到本地:
+
+```bash
+npx @flowgram.ai/cli@latest materials form-plugins/infer-inputs-plugin
+```
+
+### 目录结构讲解
+
+```plaintext
+infer-inputs-plugin/
+└── index.tsx  # 插件完整实现,包含 Schema 推断和双向转换逻辑
+```
+
+### 核心实现说明
+
+`inferInputsPlugin` 的核心功能是从 IFlowValue 对象推断 JSON Schema。对于常量值,直接使用其 `schema` 字段;对于变量引用,从作用域中查询变量类型;对于表达式和模板,推断为相应的基础类型。插件还支持 `ignoreConstantSchema` 优化,在提交时剥离常量 Schema,在初始化时自动恢复。
+
+#### 工作流程时序图
+
+```mermaid
+sequenceDiagram
+    participant Form as 表单
+    participant Plugin as inferInputsPlugin
+    participant Scope as 变量作用域
+    participant Backend as 后端
+
+    Note over Form: 表单提交
+    Form->>Plugin: onSubmit 触发
+    Plugin->>Plugin: 读取 sourceKey 数据
+
+    loop 遍历每个 IFlowValue
+        alt 类型为 constant
+            Plugin->>Plugin: 使用 value.schema
+            opt ignoreConstantSchema = true
+                Plugin->>Plugin: 剥离 schema
+            end
+        else 类型为 ref
+            Plugin->>Scope: 查询变量类型
+            Scope->>Plugin: 返回变量 Schema
+        else 类型为 expression/template
+            Plugin->>Plugin: 推断为 any/string 类型
+        end
+    end
+
+    Plugin->>Plugin: 合并所有 Schema
+    Plugin->>Form: 设置到 targetKey
+    Form->>Backend: 提交包含 Schema 的数据
+
+    Note over Form: 表单初始化
+    Backend->>Form: 返回数据(可能缺少常量 Schema)
+    Form->>Plugin: onInit 触发
+    opt ignoreConstantSchema = true
+        Plugin->>Plugin: 从 sourceKey 恢复常量 Schema
+        Plugin->>Form: 更新 targetKey
+    end
+```
+
+核心功能特点:
+
+1. **自动 Schema 推断**:扫描表单数据中的 IFlowValue 对象,自动推断其 JSON Schema
+2. **变量类型解析**:对于变量引用,从作用域中解析变量的实际类型
+3. **常量 Schema 优化**:可选地在提交时剥离常量的 Schema,减少后端数据负载
+4. **双向转换**:在表单初始化时恢复 Schema,在表单提交时生成 Schema
+
+### 依赖梳理
+
+#### flowgram API
+
+[**@flowgram.ai/editor**](https://github.com/bytedance/flowgram.ai/tree/main/packages/client/editor)
+- `defineFormPluginCreator`: 定义表单插件的工厂函数
+- `FormPlugin`: 表单插件类型定义
+- `FormPluginSetupMetaCtx`: 插件设置上下文,提供 `addFormatOnInit`、`addFormatOnSubmit` 方法
+
+[**@flowgram.ai/variable-core**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/variable-core)
+
+[**@flowgram.ai/json-schema**](https://github.com/bytedance/flowgram.ai/tree/main/packages/variable-engine/json-schema)
+- `IJsonSchema`: JSON Schema 类型定义
+
+#### 依赖的其他物料
+
+[**FlowValue**](../common/flow-value)
+- `FlowValueUtils.inferJsonSchema()`: 推断 IFlowValue 的 JSON Schema
+- `FlowValueUtils.traverse()`: 遍历嵌套的 FlowValue 结构
+- `FlowValueUtils.isConstant()`, `FlowValueUtils.isRef()`: 类型判断工具
+- `IFlowValue`: Flow 值的联合类型
+- `IFlowConstantValue`: 常量类型,包含 `schema` 字段
+- `IFlowRefValue`: 变量引用类型,包含变量路径

+ 7 - 6
packages/materials/form-materials/src/components/assign-rows/index.tsx

@@ -5,7 +5,7 @@
 
 import React from 'react';
 
-import { FieldArray, FieldArrayRenderProps } from '@flowgram.ai/editor';
+import { FieldArray } from '@flowgram.ai/editor';
 import { Button } from '@douyinfe/semi-ui';
 import { IconPlus } from '@douyinfe/semi-icons';
 
@@ -14,15 +14,16 @@ import { AssignRow, AssignValueType } from '@/components/assign-row';
 interface AssignRowsProps {
   name: string;
   readonly?: boolean;
+  defaultValue?: AssignValueType[];
 }
 
 export function AssignRows(props: AssignRowsProps) {
-  const { name, readonly } = props;
+  const { name, readonly, defaultValue } = props;
 
   return (
-    <FieldArray name={name}>
-      {({ field }: FieldArrayRenderProps<AssignValueType | undefined>) => (
-        <>
+    <FieldArray<AssignValueType | undefined> name={name} defaultValue={defaultValue}>
+      {({ field }) => (
+        <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
           {field.map((childField, index) => (
             <AssignRow
               key={childField.key}
@@ -52,7 +53,7 @@ export function AssignRows(props: AssignRowsProps) {
               Declaration
             </Button>
           </div>
-        </>
+        </div>
       )}
     </FieldArray>
   );

+ 5 - 4
packages/materials/form-materials/src/components/display-outputs/index.tsx

@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: MIT
  */
 
-import React, { useEffect } from 'react';
+import React, { useLayoutEffect } from 'react';
 
 import { IJsonSchema, JsonSchemaTypeManager, JsonSchemaUtils } from '@flowgram.ai/json-schema';
 import { useCurrentScope, useRefresh } from '@flowgram.ai/editor';
@@ -17,13 +17,14 @@ interface PropsType {
   showIconInTree?: boolean;
   displayFromScope?: boolean;
   typeManager?: JsonSchemaTypeManager;
+  style?: React.CSSProperties;
 }
 
-export function DisplayOutputs({ value, showIconInTree, displayFromScope }: PropsType) {
+export function DisplayOutputs({ value, showIconInTree, displayFromScope, style }: PropsType) {
   const scope = useCurrentScope();
   const refresh = useRefresh();
 
-  useEffect(() => {
+  useLayoutEffect(() => {
     if (!displayFromScope || !scope) {
       return () => null;
     }
@@ -50,7 +51,7 @@ export function DisplayOutputs({ value, showIconInTree, displayFromScope }: Prop
   const childEntries = Object.entries(properties || {});
 
   return (
-    <div className="gedit-m-display-outputs-wrapper">
+    <div className="gedit-m-display-outputs-wrapper" style={style}>
       {childEntries.map(([key, schema]) => (
         <DisplaySchemaTag
           key={key}