Workbench

Valibot 配置表单

用一个 Valibot object schema 同时驱动 Plugin 配置、字段信息和 Web 表单。

给配置字段加标题、说明、控件偏好时,使用 valibot-form metadata。Plugin 仍只声明一份 Valibot schema, Workbench 会自动显示配置表单;无需为普通配置另外编写 React 页面。

先给一个字段加标题

import { ,  } from '@pluxel/core'
import * as  from 'valibot-form'
import * as  from 'valibot'

@()
export class  extends  {
	private readonly  = this..(
		.({
			: .(.(.(), .({ : '启用服务' })), true),
		}),
	)
}

构建并运行插件,标准配置页应出现“启用服务”开关,初始值为开启。 f.formMeta() 只描述显示方式;字段是否必填、默认值和有效范围仍由 Valibot 决定。 保存与运行时应用的区别见插件配置。

最小配置与渲染结果

下面是覆盖多种控件的完整参考例子。按需查找开关、分段选择、URL、整数、嵌套对象和列表; 无需在第一个 Plugin 中一次性采用全部控件。展开预览可直接操作表单,比较原始 Input 与校验后的 Output。


const  = .({
	: .(
		.(
			.(),
			.({
				: '启用示例服务',
				: 'schema 默认值会进入 normalized config',
				: { : 'runtime', : '运行时' },
			}),
		),
		true,
	),
	: .(
		.(
			.(['development', 'production'] as ),
			.({ : '运行环境', : 'runtime' }),
			.({
				: 'segmented',
				: { : '开发', : '生产' },
			}),
		),
		'development',
	),
	: .(
		.(
			.(),
			.(),
			.({
				: '上游地址',
				: 'URL 约束来自 schema;表单只负责编辑。',
				: { : 'network', : '网络与重试' },
			}),
			.({ : 'https://api.example.com' }),
		),
		'https://api.example.com',
	),
	: .(
		.(
			.(),
			.(),
			.(1),
			.(65535),
			.({ : '监听端口', : 'network' }),
			.({ : 1 }),
		),
		8787,
	),
	: .(
		.(
			.({
				: .(
					.(
						.(),
						.(),
						.(1),
						.(10),
						.({ : '最大次数' }),
						.({ : 1 }),
					),
					3,
				),
				: .(
					.(
						.(),
						.(),
						.(100),
						.({ : '退避时间(毫秒)' }),
						.({ : 100 }),
					),
					250,
				),
			}),
			.({ : '重试策略', : 'network' }),
			.({ : 'card' }),
		),
		{
			: 3,
			: 250,
		},
	),
	: .(
		.(
			.(.(.(), .())),
			.({ : '允许的 Origin', : 'network' }),
			.({
				: 'list',
				: 'Origin',
				: '添加 Origin',
				: 'https://api.example.com',
			}),
		),
		['https://api.example.com'],
	),
})

@({ : 'Example' })
export class  extends  {
	private readonly  = this..()

	override () {
		(this.., { : this.. })
	}
}
配置渲染预览 · 表单、Input 与 Output

当字段既有默认值又有表单 metadata 时,让 v.optional() 包住完成后的 v.pipe():v.optional(v.pipe(base, constraints, metadata), default)。这样默认值属于外层可选语义,字段 extractor 解包 optional 后仍能读取内层 metadata;不要写成 v.pipe(v.optional(base, default), metadata)。

Plugin 的声明和读取时机见配置规则。

metadata 做什么

valibot-form 的 core entry 不依赖 React/Mantine,适合 runtime config、CLI prompt、配置文件编辑器和 schema inspection:

import * as  from 'valibot'
import * as  from 'valibot-form'

const  = .({
	: .(
		.(['development', 'production'] as ),
		.({ : '运行环境' }),
		.({
			: 'segmented',
			: { : '开发', : '生产' },
		}),
	),
})

const  = .()

常用映射:

Valibot schemametadata默认 web 控件
v.string()stringMetaTextInput
v.number()numberMetaNumberInput
v.boolean()—Switch
v.picklist()picklistMetaSelect
v.array()arrayMetaList
v.record()recordMetaTable
v.object()objectMetaCard/stack
v.variant() / unionunionMetaSelect/segmented

类型入口

类型直接从 package 源码导出。下面的示例由 Twoslash 对当前 workspace 类型检查,不在文档中维护另一份类型声明:

import type { FormMeta,  } from 'valibot-form'
import type {  } from 'valibot-form/web'

type MetadataKeys = keyof FormMeta
type MetadataKeys = keyof FormMeta
type FormProps = keyof <>
type FormProps = "fields" | "formOpts" | "schema" | keyof AutoFormSharedProps

formMeta() 的 title / description 使用 Valibot 标准 metadata,help、section、layout、disabled、readOnly 和 hidden 仍是表单展示偏好;类型对应的 *Meta() 只负责控件偏好。requiredness、选项、格式和范围仍来自 Valibot schema,例如 v.optional()、v.url()、v.minValue()、v.maxValue() 和 v.integer()。原生 v.title()、v.description() 与 v.metadata({ title, description }) 也会按 pipe 顺序互操作,但标准示例使用一次 formMeta() 集中声明。

需要编辑 schema 或查看类型补全时,打开独立的配置 Playground。

Web adapter

只有在自己的 React 应用中需要自动表单,才从 valibot-form/web 导入。标准 Workbench 配置页已包含它。 独立应用需要安装 React、Mantine、TanStack Form、Tabler Icons 和 dnd-kit:

npx nypm add valibot-form valibot react react-dom @mantine/core @mantine/hooks @tanstack/react-form @tabler/icons-react @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

export function () {
	return (
		<>
			<
				={}
				={{
					: { : 'development' },
					: async ({  }) => (),
				}}
			>
				<. />
				<.>
					{({ , , , ,  }) => (
						<>
							< ="button" ={() => ()} ={! || }>
								重置
							</>
							< ="button" ={} ={! || }>
								保存
							</>
						</>
					)}
				</.>
			</>
		</>
	)
}

上例是独立 React 应用,因此自行导入 Mantine CSS。放进 Workbench View 时,仍需自己的 MantineProvider, 但应删除 @mantine/core/styles.css 导入,基础 CSS 已由宿主加载;见页面资源参考。

AutoForm 负责根据 schema metadata 规划和渲染字段;配置 authority 仍然是 runtime 的 configs.use() 校验流程。把表单值送回 host API 前,服务端必须再次用同一个 schema 校验,不能把浏览器表单当作信任边界。

嵌套编辑与错误反馈

Object、数组行和当前 Union 分支中的可编辑字段使用完整的 TanStack 字段路径,例如 database.host、servers[0].host。各字段独立记录 blur 和错误;数组删除、重排使用 TanStack 的数组操作, 交互状态随行移动,受影响的校验错误重新校验或清除。

Workbench 的配置保存和 Content action 会把服务端错误放到对应的已显示字段;隐藏字段、未激活分支、 无法准确定位的路径错误保留在表单摘要。编辑字段会清除该字段的旧服务端错误和表单摘要, 其他字段的错误继续显示;开始下一次提交时清除上一轮服务端错误。修改后可保留草稿再次提交。 请求期间继续编辑时,迟到响应不会覆盖新草稿或给新值挂上旧校验错误;配置保存成功仍会更新已保存基线, 新草稿保留为未保存修改。Content action 有新草稿时也不会自动清空或关闭表单;操作反馈仍报告已提交请求的结果。

配置分区保留独立的保存基线与撤销范围;保存当前分区不会清空其他分区的草稿。当前保存和全部保存共享请求流程, 请求结束前不能启动另一笔配置保存,但可以继续编辑。网络失败后保留草稿并允许重试;保存已确认成功时, 后续运行状态刷新失败不会将这笔保存报告为失败。

独立使用 AutoForm 时, form.setErrorMap({ onServer: { fields: { 'database.host': '地址不可用' } } }) 可设置字段错误; 编辑该字段会清除它的旧服务端错误。跨字段错误与表单摘要的失效策略由调用方决定。

reset() 同时重置表单和局部编辑草稿,包括 Union 的非激活分支缓存、数组与 Record 的新增草稿。 在提交回调中调用 formApi.reset() 具有相同效果。切换字段计划时,使用 resetKey 明确开始新的编辑会话。

formOpts.defaultValues 未提供或为 undefined 时,使用 schema 默认值。控件、context 和重置共享同一次默认值解析结果, 因此动态默认值工厂生成的值也保持一致。AutoForm.Actions 提供的 setValues 按 TanStack 字段路径逐项更新, 例如 setValues({ 'database.host': 'db.example' });它保留其他值,不把带点的 key 当作顶层字面量名称。

Record 内无法被路径准确表示的字面量 key(如 x.y、0 或空字符串)保持原样,通过可绑定的祖先字段编辑; 这类值没有独立的 TanStack 字段路径,Workbench 将相应服务端错误显示在摘要。 如果顶层 key 本身无法被 TanStack 路径准确表示,则显示只读说明并保留原值,避免写入错误位置。 需要编辑这类数据时,将它放在普通命名的 Record 或 Object 字段内。

传入 schema 用于字段规划和默认值,不会自动安装客户端 validator 或将编辑值转换成 schema output。 独立表单可通过 formOpts.validators 显式选择客户端校验时机;Workbench 的 portable 字段计划仍由服务端执行完整校验。

与 Pluxel 配置界面的边界

valibot-form 提供 schema metadata、字段提取和可选 Web adapter,不提供 Pluxel Plugin 发现、配置传输或持久化 API。自定义配置界面应直接接收 browser-safe 的 schema,并通过应用自己的服务端接口提交修改;服务端继续使用同一 schema 校验输入。

Pluxel Workbench 内置的 Plugin 配置页由宿主读取 runtime config metadata。Plugin 作者只声明 this.configs.use(Config),不调用 Workbench 内部的 schema projection 或配置 patch 实现。

最后更新于

本页目录