import type { ReactNode } from "react"; import { cn } from "./utils/cn"; /** * PropsConfigForm - 基于 JSON Schema 的插件配置表单(portal-shell spec §7.3) * * 根据插件的 propsSchema(JSON Schema)自动渲染配置表单, * admin 通过此表单配置插件的默认 props。 * * 支持的字段类型: * - string:文本输入 * - number:数字输入 * - integer:整数输入 * - boolean:复选框 * - enum:下拉选择 * - object:嵌套对象(递归渲染) * * v2.0 令牌迁移:shadcn 标准令牌 * * @example * console.log(v)} * /> */ /** JSON Schema 类型定义(与 portal-shell spec §5.1 对齐) */ export interface PropsJsonSchema { type?: string; properties?: Record; items?: PropsJsonSchema; description?: string; default?: unknown; enum?: unknown[]; [key: string]: unknown; } export interface PropsConfigFormProps { /** JSON Schema */ schema: PropsJsonSchema; /** 当前值 */ value: Record; /** 值变更回调 */ onChange: (value: Record) => void; /** 自定义类名 */ className?: string; } export function PropsConfigForm({ schema, value, onChange, className, }: PropsConfigFormProps): ReactNode { const properties = schema.properties; if (!properties) { return

此插件无可配置项

; } return (
{Object.entries(properties).map(([key, fieldSchema]) => ( { onChange({ ...value, [key]: fieldValue }); }} /> ))}
); } interface FieldRendererProps { name: string; schema: PropsJsonSchema; value: unknown; onChange: (value: unknown) => void; } function FieldRenderer({ name, schema, value, onChange, }: FieldRendererProps): ReactNode { const fieldType = schema.type ?? "string"; const label = schema.description ?? name; // enum 下拉 if (schema.enum && schema.enum.length > 0) { return ( ); } // boolean 复选框 if (fieldType === "boolean") { return ( ); } // number / integer 数字输入 if (fieldType === "number" || fieldType === "integer") { return ( ); } // object 嵌套递归 if (fieldType === "object" && schema.properties) { const objValue = (value as Record) ?? {}; return (
{label}
{Object.entries(schema.properties).map(([childKey, childSchema]) => ( { onChange({ ...objValue, [childKey]: childValue }); }} /> ))}
); } // string 默认文本输入 return ( ); }