Files
khata-ui/react-openapi/src/components/fields/renderers/DiscriminatorField.tsx
2026-07-17 14:31:39 +05:30

75 lines
2.4 KiB
TypeScript

import React, { useCallback } from "react";
import { Box, FormControl, InputLabel, Select, MenuItem, Typography } from "@mui/material";
import type { FieldConfig } from "../../../types";
import { FormFieldRenderer } from "../FormFieldRenderer";
interface Props {
field: FieldConfig;
value: any;
onChange: (value: any) => void;
error?: string;
}
export function DiscriminatorField({ field, value, onChange, error }: Props) {
const options = field.oneOfOptions ?? [];
const discProp = field.discriminatorProperty ?? "type";
const currentType = value?.[discProp] ?? "";
function defaultFieldValue(field: FieldConfig): any {
if (field.enumValues) return field.enumValues[0];
if (field.isArray) return [];
if (field.type === "object") return {};
if (field.type === "number" || field.type === "integer") return 0;
return null;
}
const handleTypeChange = useCallback((e: any) => {
const newType = e.target.value;
const option = options.find((o) => o.value === newType);
const newValue: Record<string, any> = { [discProp]: newType };
if (option) {
for (const f of option.fields) {
newValue[f.name] = defaultFieldValue(f);
}
}
onChange(newValue);
}, [discProp, onChange, options]);
const handleFieldChange = useCallback((fieldName: string, fieldValue: any) => {
onChange({ ...(value ?? {}), [fieldName]: fieldValue });
}, [onChange, value]);
const activeFields = options.find((o) => o.value === currentType)?.fields ?? [];
return (
<Box>
<FormControl fullWidth size="small" sx={{ mb: 2 }}>
<InputLabel>{field.label}</InputLabel>
<Select
value={currentType}
label={field.label}
onChange={handleTypeChange}
error={!!error}
>
<MenuItem value="" disabled>Select type</MenuItem>
{options.map((opt) => (
<MenuItem key={opt.value} value={opt.value}>{opt.label}</MenuItem>
))}
</Select>
</FormControl>
{currentType && activeFields.length > 0 && (
<Box sx={{ pl: 2, borderLeft: "2px solid", borderColor: "divider" }}>
{activeFields.map((f) => (
<FormFieldRenderer
key={f.name}
field={f}
value={value?.[f.name]}
onChange={(v) => handleFieldChange(f.name, v)}
/>
))}
</Box>
)}
</Box>
);
}