import * as React from "react" import * as LucideIcons from "lucide-react" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Slider } from "@/components/ui/slider" import { Switch } from "@/components/ui/switch" import { Textarea } from "@/components/ui/textarea" import type { FieldSchema } from "@/types/config-schema" export interface DynamicFieldProps { schema: FieldSchema value: unknown onChange: (value: unknown) => void // eslint-disable-next-line @typescript-eslint/no-unused-vars fieldPath?: string // 用于 Hook 系统(未来使用) } /** * DynamicField - 根据字段类型和 x-widget 渲染对应的 shadcn/ui 组件 * * 渲染逻辑: * 1. x-widget 优先:如果 schema 有 x-widget,使用对应组件 * 2. type 回退:如果没有 x-widget,根据 type 选择默认组件 */ export const DynamicField: React.FC = ({ schema, value, onChange, }) => { /** * 渲染字段图标 */ const renderIcon = () => { if (!schema['x-icon']) return null const IconComponent = LucideIcons[schema['x-icon'] as keyof typeof LucideIcons] as React.ComponentType<{ className?: string }> | undefined if (!IconComponent) return null return } /** * 根据 x-widget 或 type 选择并渲染对应的输入组件 */ const renderInputComponent = () => { const widget = schema['x-widget'] const type = schema.type // x-widget 优先 if (widget) { switch (widget) { case 'slider': return renderSlider() case 'switch': return renderSwitch() case 'textarea': return renderTextarea() case 'select': return renderSelect() case 'custom': return (
Custom field requires Hook
) default: // 未知的 x-widget,回退到 type break } } // type 回退 switch (type) { case 'boolean': return renderSwitch() case 'number': case 'integer': return renderNumberInput() case 'string': return renderTextInput() case 'select': return renderSelect() case 'array': return (
Array fields not yet supported
) case 'object': return (
Object fields not yet supported
) case 'textarea': return renderTextarea() default: return (
Unknown field type: {type}
) } } /** * 渲染 Switch 组件(用于 boolean 类型) */ const renderSwitch = () => { const checked = Boolean(value) return ( onChange(checked)} /> ) } /** * 渲染 Slider 组件(用于 number 类型 + x-widget: slider) */ const renderSlider = () => { const numValue = typeof value === 'number' ? value : (schema.default as number ?? 0) const min = schema.minValue ?? 0 const max = schema.maxValue ?? 100 const step = schema.step ?? 1 return (
onChange(values[0])} min={min} max={max} step={step} />
{min} {numValue} {max}
) } /** * 渲染 Input[type="number"] 组件(用于 number/integer 类型) */ const renderNumberInput = () => { const numValue = typeof value === 'number' ? value : (schema.default as number ?? 0) const min = schema.minValue const max = schema.maxValue const step = schema.step ?? (schema.type === 'integer' ? 1 : 0.1) return ( onChange(parseFloat(e.target.value) || 0)} min={min} max={max} step={step} /> ) } /** * 渲染 Input[type="text"] 组件(用于 string 类型) */ const renderTextInput = () => { const strValue = typeof value === 'string' ? value : (schema.default as string ?? '') return ( onChange(e.target.value)} /> ) } /** * 渲染 Textarea 组件(用于 textarea 类型或 x-widget: textarea) */ const renderTextarea = () => { const strValue = typeof value === 'string' ? value : (schema.default as string ?? '') return (