@bluprynt/forms-builder

中文文档
4.2.0发布于 2026/10/21TypeScriptESM + CJS零依赖近 30 天下载 2.1万

Headless React component for building and editing form schemas with drag-and-drop reordering. Pairs with @bluprynt/forms-core to handle schema mutations via FormDefinitionEditor.

原始使用文档
文档目录9 节
  1. Key Capabilities
  2. Installation
  3. Quick Start
  4. Handling Selection
  5. Render Component Props
  6. FieldRenderProps
  7. SectionRenderProps
  8. AddPlaceholderRenderProps
  9. Documentation

@bluprynt/forms-builder

Headless React component for building and editing form schemas with drag-and-drop reordering. Pairs with @bluprynt/forms-core to handle schema mutations via FormDefinitionEditor.

Key Capabilities

  • Drag-and-drop reordering — reorder fields and sections with depth-aware nesting via @dnd-kit, respecting the maximum nesting depth of 3 levels.
  • Schema CRUD — add, update, and remove fields and sections. All mutations go through FormDefinitionEditor from @bluprynt/forms-core.
  • Headless architecture — all rendering is delegated to components you provide (container, section, field, addPlaceholder), so the package has zero UI opinions.
  • Depth-aware nesting — horizontal drag offset controls nesting depth. Only sections can accept nested children, enforced during drag projection.
  • Add placeholders — automatic insertion points at the end of each section and at the root level for adding new items.

Installation

npm install @bluprynt/forms-builder @bluprynt/forms-core ajv react react-dom @dnd-kit/abstract @dnd-kit/dom @dnd-kit/helpers @dnd-kit/react @dnd-kit/state

@bluprynt/forms-core, react, react-dom, and @dnd-kit/* packages are peer dependencies and must be installed in your project.

Quick Start

import { useState, type FC } from 'react'
import { FormBuilder } from '@bluprynt/forms-builder'
import type {
  FieldRenderProps,
  SectionRenderProps,
  AddPlaceholderRenderProps,
  NewContentItem,
} from '@bluprynt/forms-builder'
import type { FormDefinition } from '@bluprynt/forms-core'

const MyField: FC<FieldRenderProps> = ({ ref, handleRef, item, isDragging, onRemove }) => (
  <div ref={ref} style={{ opacity: isDragging ? 0.5 : 1 }}>
    <span ref={handleRef}>⠿</span>
    {item.label}
    <button onClick={onRemove}>Remove</button>
  </div>
)

const MySection: FC<SectionRenderProps> = ({ ref, handleRef, item, isDragging }) => (
  <div ref={ref} style={{ opacity: isDragging ? 0.5 : 1 }}>
    <span ref={handleRef}>⠿</span>
    {item.title}
  </div>
)

const MyAddPlaceholder: FC<AddPlaceholderRenderProps> = ({ onAdd }) => (
  <button onClick={() => onAdd({ type: 'string', label: 'New Field' })}>
    + Add Field
  </button>
)

const Builder: FC = () => {
  const [definition, setDefinition] = useState<FormDefinition>(initialDefinition)

  return (
    <FormBuilder
      definition={definition}
      container={({ children }) => <div>{children}</div>}
      section={MySection}
      field={MyField}
      addPlaceholder={MyAddPlaceholder}
      selectedId={null}
      onDefinitionChange={setDefinition}
    />
  )
}

Handling Selection

Track which item is selected by passing selectedId. Each field and section component receives isSelected:

const [selectedId, setSelectedId] = useState<number | null>(null)

<FormBuilder
  definition={definition}
  container={({ children }) => <div>{children}</div>}
  section={(props) => (
    <div ref={props.ref} onClick={() => setSelectedId(props.id)}
      style={{ outline: props.isSelected ? '2px solid blue' : 'none' }}>
      <span ref={props.handleRef}>⠿</span>
      {props.item.title}
    </div>
  )}
  field={(props) => (
    <div ref={props.ref} onClick={() => setSelectedId(props.id)}
      style={{ outline: props.isSelected ? '2px solid blue' : 'none' }}>
      <span ref={props.handleRef}>⠿</span>
      {props.item.label}
    </div>
  )}
  addPlaceholder={MyAddPlaceholder}
  selectedId={selectedId}
  onDefinitionChange={setDefinition}
/>

Render Component Props

FieldRenderProps

PropertyTypeDescription
ref(element: Element | null) => voidSortable item ref — attach to outermost DOM element
handleRef(element: Element | null) => voidDrag handle ref — attach to the drag handle element
idnumberField ID
depthnumberNesting depth (0 = root level)
indexnumberPosition index in the flat list
parentIdnumber | nullParent section ID, or null for root-level
typeFieldTypeField type ('string', 'number', etc.)
itemAnyFieldContentItemFull field content item from the definition. This is FieldContentItem | StaticFieldContentItem, so item.label is string | undefined — narrow with item.type === 'static' to reach item.text.
isDraggingbooleantrue when this item is being dragged
isSelectedbooleantrue when this item's ID matches selectedId
onAdd(item: NewContentItem) => numberAdd a new item to this field's parent section; returns the new ID
onRemove() => voidRemove this field
onChange(item: ContentItem) => voidUpdate this field

SectionRenderProps

Same shape as FieldRenderProps except:

PropertyTypeDescription
itemSectionContentItemFull section content item from the definition
onAdd(item: NewContentItem) => numberAdd a new item inside this section; returns the new ID
onRemove() => voidRemove this section and all descendants

AddPlaceholderRenderProps

PropertyTypeDescription
depthnumberNesting depth where the placeholder appears
parentIdnumber | nullParent section ID, or null for root-level
onAdd(item: NewContentItem) => numberAdd a new item at this location; returns the new ID
onChange(id: number, item: ContentItem) => voidUpdate an existing item by ID

Documentation

DocumentDescription
ArchitectureProject structure, module dependency graph, drag-and-drop flow, tree flattening
API ReferenceComplete public API — components, hooks, types, props tables
Development GuideHow to build, test, lint, and extend the builder

版本与发布记录

@bluprynt/forms-builder 共发布 6 个版本,首次发布于 2026/03/20;过去 12 个月发布了 6 个版本。

版本发布日期距今
4.2.0latest2026/10/2117 天前
4.1.02026/09/221 个月前
4.0.12026/06/294 个月前
3.0.02026/03/247 个月前
2.0.02026/03/247 个月前
1.0.02026/03/207 个月前

关于 @bluprynt/forms-builder 的常见问题

@bluprynt/forms-builder 是什么?

Headless React component for building and editing form schemas with drag-and-drop reordering. Pairs with @bluprynt/forms-core to handle schema mutations via FormDefinitionEditor.

如何安装 @bluprynt/forms-builder?

在项目目录运行 npm install @bluprynt/forms-builder,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.0.0 || ^19.0.0)、react-dom(^18.0.0 || ^19.0.0)、@dnd-kit/dom(^0.5.0)、@dnd-kit/react(^0.5.0)、@dnd-kit/state(^0.5.0)、@dnd-kit/helpers(^0.5.0)、@dnd-kit/abstract(^0.5.0)、@bluprynt/forms-core(^4.2.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bluprynt/forms-builder 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bluprynt/forms-builder 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@bluprynt/forms-builder 可以商用吗?

@bluprynt/forms-builder 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@bluprynt/forms-builder 的下载量有多少?

根据 npm 官方下载统计,@bluprynt/forms-builder 在 2026/10/09 – 2026/11/07 这 30 天内被下载 20,678 次,日均约 689 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bluprynt/forms-builder 还在维护吗?

最新版本 4.2.0 发布于 2026/10/21(17 天前);至今共发布 6 个版本,其中过去 12 个月发布了 6 个;首次发布于 2026/03/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。