Files
khata-ui/react-openapi/components/fields/FormField.tsx

102 lines
2.7 KiB
TypeScript

import * as React from 'react';
import { TextField as MuiTextField } from '@mui/material';
import { ResourceField } from '../../types/config';
import { FieldComponentProps, FieldComponents } from '../../types/overrides';
import { defaultFieldComponents } from './DefaultFieldComponents';
import ObjectField from './ObjectField';
import ImageUploadField from './ImageUploadField';
interface FormFieldProps {
name: string;
field: ResourceField;
value: any;
onChange: (val: any) => void;
disabled?: boolean;
uploadFile: (file: File) => Promise<string | null>;
uploading: boolean;
baseUrl: string;
relationDataMap?: Record<string, any[]>;
components?: FieldComponents;
}
function FallbackField({ field, value }: FieldComponentProps) {
return (
<MuiTextField
fullWidth
label={field.label}
value={typeof value === 'object' ? JSON.stringify(value) : value || ''}
disabled
/>
);
}
export default function FormField({
name,
field,
value,
onChange,
disabled,
uploadFile,
uploading,
baseUrl,
relationDataMap = {},
components: componentsProp,
}: FormFieldProps) {
const components = React.useMemo(
() => ({ ...defaultFieldComponents, ...componentsProp }),
[componentsProp],
);
const fieldProps: FieldComponentProps = {
name,
field,
value,
onChange,
disabled,
baseUrl,
relationDataMap,
uploadFile,
uploading,
};
// 1. Object (recursive) - requires parent FormField for recursion
if (field.type === 'object' && field.schema && !field.relation) {
const renderChild = (childProps: FieldComponentProps) => (
<FormField
name={childProps.name}
field={childProps.field}
value={childProps.value}
onChange={childProps.onChange}
disabled={childProps.disabled}
uploadFile={childProps.uploadFile!}
uploading={childProps.uploading!}
baseUrl={childProps.baseUrl!}
relationDataMap={childProps.relationDataMap}
components={componentsProp}
/>
);
return <ObjectField {...fieldProps} renderField={renderChild} />;
}
// 2. Image
if (field.type === 'image') {
const ImageField = components.image || ImageUploadField;
return <ImageField {...fieldProps} />;
}
// 3. Relation
if (field.relation && relationDataMap[field.relation]) {
const RelationFieldComp = components.relation || defaultFieldComponents.relation!;
return <RelationFieldComp {...fieldProps} />;
}
// 4. Lookup by field type
const Component = components[field.type];
if (Component) {
return <Component {...fieldProps} />;
}
// 5. Fallback for unknown types
return <FallbackField {...fieldProps} />;
}