npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@whynotsnow/dynamic-form

v4.0.0

Published

DynamicForm 是一个基于 React 和 Ant Design 的动态表单组件,支持复杂的表单联动、自定义处理器、状态管理和性能优化。

Downloads

421

Readme

DynamicForm

@whynotsnow/dynamic-form 是一个基于 React、TypeScript 和 Ant Design 的动态表单库。它用配置描述表单结构,用 form-chain-effect-engine 执行字段联动,并通过 Runtime Layer 统一处理字段是否渲染、是否提交、是否可编辑、是否校验等运行时策略。

项目能力

  • 🚀 通过 formConfig 配置化渲染 Ant Design 表单。
  • 🗂️ 支持平铺表单、分组表单和 4.0 统一节点树 nodes
  • 🧱 支持递归 container、container name 前缀和 repeatable container。
  • 🔗 支持字段、分组和 container 级 dependents + effect 联动。
  • 🧩 支持静态初始值和函数式初始值。
  • 🛠️ 内置 effect 结果处理器,可处理字段值、字段行为、分组可见性、字段渲染 props 和全局 UI 配置。
  • 🎨 支持通过 componentRegistry 注册自定义字段组件。
  • 🧱 支持通过 Field Module、Compiler 和 Adapter 管线复用领域字段配置。
  • 📐 支持声明式同步 Rule Engine,并将规则编译为标准 effects。
  • 🔄 支持 JsonSchema、OpenAPI 和 metadata 输入适配。
  • 🧩 CompiledDynamicForm 可直接渲染 compiler/adapter 产物并自动接入模块组件。
  • 🪝 支持从字段项到整个表单体的分层 render hooks。
  • 🧠 使用 Runtime Layer 统一解析 renderedsubmitableeditablereadonlydisabledvalidatable 等能力。
  • 🧱 Ant Design Form 仍然是真实表单值和校验运行时状态的唯一来源。
  • 🧭 支持通过 name: NamePath 分离稳定字段 id 与嵌套值路径,旧配置默认继续使用 id

安装

pnpm add @whynotsnow/dynamic-form antd react react-dom

Peer dependencies(对等依赖):

  • react >= 17
  • react-dom >= 17
  • antd >= 5

基础用法

import { Form } from 'antd';
import { DynamicForm, useInitHandlers } from '@whynotsnow/dynamic-form';
import type { FormConfig } from '@whynotsnow/dynamic-form';

const formConfig: FormConfig = {
  fields: [
    {
      id: 'name',
      label: 'Name',
      component: 'TextInput',
      rules: [{ required: true, message: 'Please enter a name' }]
    },
    {
      id: 'employeeCount',
      label: 'Employee Count',
      component: 'NumberInput',
      dependents: ['companySize'],
      effect: (value) => ({
        value,
        componentProps: { min: 0 }
      })
    },
    {
      id: 'companySize',
      label: 'Company Size',
      component: 'Select',
      componentProps: {
        options: [
          { label: 'Small', value: 'small' },
          { label: 'Large', value: 'large' }
        ]
      }
    }
  ]
};

export function Example() {
  const [form] = Form.useForm();
  const { isInitialized, error } = useInitHandlers({});

  if (!isInitialized) return null;
  if (error) return <div>{error.message}</div>;

  return (
    <DynamicForm
      form={form}
      formConfig={formConfig}
      submitButtonText="Submit"
      onSubmit={(values) => console.log(values)}
    />
  );
}

核心 API

主要导出定义在 packages/dynamic-form/src/exports.ts

  • DynamicForm
  • CompiledDynamicForm
  • DynamicFormProvider
  • FormChainEffectEngineWrapper
  • useInitHandlers
  • useStoreInit
  • useFormChainContext
  • ComponentRegistryManager
  • DefaultRegistryFieldComponents
  • getDefaultConfig
  • processFormConfig
  • compileFormConfig
  • ModuleRegistryManager
  • defaultModuleRegistry
  • AdapterRegistryManager
  • defaultAdapterRegistry
  • adaptModuleConfigs
  • compileAdaptedFormConfig
  • JsonSchemaAdapter
  • OpenApiAdapter
  • MetadataAdapter
  • RuleEngine
  • createRuleEngine
  • compileRulesToEffect
  • evaluateRule
  • DynamicFormPropsFormConfig、compiler、adapter、rule、render hook 和组件注册相关公共类型。

Rule Engine

DynamicForm 包含声明式 Rule Engine,用于模块化表单的同步联动规则。规则会被编译成标准 effects,因此渲染层和 runtime provider 不需要变化。

import { compileFormConfig, ModuleRegistryManager } from '@whynotsnow/dynamic-form';

const registry = new ModuleRegistryManager();

registry.register({
  type: 'CompanyName',
  createConfig: () => ({
    id: 'companyName',
    label: 'Company Name',
    component: 'TextInput'
  })
});

const compiled = compileFormConfig(
  {
    fields: [
      {
        type: 'CompanyName',
        id: 'companyName',
        rules: [
          {
            when: { field: 'customerType', equals: 'company' },
            then: { action: 'show' }
          },
          {
            when: { field: 'customerType', notEquals: 'company' },
            then: { action: 'hide' }
          }
        ]
      }
    ]
  },
  { registry }
);

当前规则支持同步联动动作:showhideenabledisablereadonlyeditablesetValueclearValue。Group/container rules 仅支持 showhide

Rule 是字段所属的 per-field 规则,不支持 target 配置。一个源字段影响多个字段时,应在每个被影响字段上分别声明 rule;compiler 会从 when 条件推导相同的 dependents,再由 form-chain-effect-engine 触发这些字段各自的 effect。

DynamicForm props 分为两类:

  • 引擎层 props:formConfigform、可选 valuesuiConfigenableInitializationCheckcheckDelay
  • UI 层 props:可选 onSubmitsubmitButtonTextcomponentRegistryrenderFormInnerrenderGroupsrenderGroupItemrenderFieldsrenderFieldItem

文档入口

设计理念

  • 配置优先:业务表单通过字段、分组、依赖和 UI 配置描述。
  • 值归 Ant Design Form:reducer 不维护重复的 values、errors、touched 或 validating 状态。
  • Runtime 是策略边界:渲染、提交、编辑和校验能力从同一份状态快照统一解析。
  • 扩展优先于分叉:通过自定义组件、effect 结果处理器和 render hooks 覆盖业务差异。
  • 默认渲染保持简单:默认使用 Ant Design FormRowColCardButton

4.0 配置管线

当前版本在现有运行时主流程之前提供可选的 Adapter、Rule 和 Compiler 管线。JsonSchema、OpenAPI 和 metadata 输入会先归一化为结构化 ModuleFormConfig,再编译成标准 FormConfig。字段可以通过 groupId 加入 legacy group,也可以通过 nodes 声明递归 FieldNode / ContainerNode 树;Schema 无法携带的函数 effect 可通过 groupOverrides 在编译前注入。

FormConfig.nodes 是 4.0 的结构性入口。ContainerNode.name 会成为后代字段 Ant Design NamePath 前缀;repeatable: true 的 container 通过 Ant Design Form.List 渲染已有重复项。旧的 fieldsgroups 和 mixed 配置继续兼容。

项目结构

packages/dynamic-form/   npm 发布包、源码和构建配置
  src/                   库源码
  docs/                  库文档
  dist/                  构建产物
apps/docs-site/          Docusaurus 文档站
demos/                   Vite demos 和可复用 demo 组件
tests/                   Node test 文件和 demo 测试数据
docs/                    monorepo 级文档

开发命令

pnpm run start       # 启动 Vite demos
pnpm run type-check  # TypeScript 检查
pnpm run lint:check  # ESLint 检查,不自动修复
pnpm run test        # Node test runner
pnpm run build       # 构建库产物

当前仓库存在 pnpm-lock.yaml,默认使用 pnpm。

当前说明

项目当前面向基于 Ant Design 的 React 应用。内置字段组件包括 TextInputPasswordNumberInputSelectSelectFieldDatePickerSwitchRateTextDisplayCheckboxGroupTextArea

Schema Adapters

DynamicForm 提供 JsonSchemaAdapterOpenApiAdapterMetadataAdapter

import { adaptModuleConfigs } from '@whynotsnow/dynamic-form';

const moduleFormConfig = adaptModuleConfigs(
  {
    type: 'object',
    properties: {
      name: {
        type: 'string',
        metadata: { module: 'TextInputModule' }
      }
    }
  },
  { adapterType: 'json-schema' }
);

Schema adapters 要求字段显式声明 module metadata,不会根据 schema primitive type 自动猜测 UI。输出为 { fields, groups? };顶层 x-dynamic-form.groups 与属性级 groupId 控制分组,函数 effect 通过 groupOverrides 合并。Schema required 映射为字段 required 语义,最终 AntD 校验规则由默认 renderer 统一合并。