100 lines
3.9 KiB
TypeScript
100 lines
3.9 KiB
TypeScript
import {useState} from "react";
|
|
import {Check, Plus, Trash2, X} from "lucide-react";
|
|
import type { JSONSchemaType } from "../defs/types";
|
|
import PropertyEditor from "./PropertyEditor.tsx";
|
|
import styles from "../defs/styles.tsx";
|
|
import type {FieldVisibility} from "../defs/interfaces.tsx";
|
|
|
|
export const DefsEditor = ({
|
|
defs,
|
|
onChange,
|
|
rootSchema,
|
|
visibility,
|
|
}: {
|
|
defs: Record<string, JSONSchemaType>,
|
|
onChange: (defs: Record<string, JSONSchemaType>) => void,
|
|
rootSchema: JSONSchemaType,
|
|
visibility: FieldVisibility,
|
|
}) => {
|
|
const [isAddingDef, setIsAddingDef] = useState(false);
|
|
const [newDefName, setNewDefName] = useState('');
|
|
|
|
const handleAddDef = () => {
|
|
if (newDefName && !defs[newDefName]) {
|
|
const newDefs = { ...defs };
|
|
newDefs[newDefName] = { type: 'object', properties: {} };
|
|
onChange(newDefs);
|
|
setNewDefName('');
|
|
setIsAddingDef(false);
|
|
}
|
|
};
|
|
|
|
const handleDeleteDef = (defName: string) => {
|
|
const newDefs = { ...defs };
|
|
delete newDefs[defName];
|
|
onChange(Object.keys(newDefs).length ? newDefs : {});
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h2 className="text-lg font-semibold">Definitions ($defs)</h2>
|
|
{!isAddingDef ? (
|
|
<button
|
|
onClick={() => setIsAddingDef(true)}
|
|
className="text-blue-500 hover:text-blue-700 flex items-center"
|
|
>
|
|
<Plus size={16} className="mr-1" /> Add Definition
|
|
</button>
|
|
) : (
|
|
<div className="flex items-center">
|
|
<input
|
|
type="text"
|
|
value={newDefName}
|
|
onChange={(e) => setNewDefName(e.target.value)}
|
|
className="border border-gray-300 rounded px-2 py-1 mr-2"
|
|
placeholder="Definition name"
|
|
/>
|
|
<button onClick={handleAddDef} className="text-green-600 mr-1">
|
|
<Check size={16} />
|
|
</button>
|
|
<button onClick={() => {
|
|
setIsAddingDef(false);
|
|
setNewDefName('');
|
|
}} className="text-red-600">
|
|
<X size={16} />
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{defs && Object.entries(defs).map(([defName, defSchema]) => (
|
|
<div key={defName} className={styles.card}>
|
|
<div className="flex items-center justify-between mb-2">
|
|
<h3 className="font-medium">{defName}</h3>
|
|
<button onClick={() => handleDeleteDef(defName)} className="text-red-500 hover:text-red-700">
|
|
<Trash2 size={16} />
|
|
</button>
|
|
</div>
|
|
<PropertyEditor
|
|
schema={defSchema}
|
|
path={`$defs.${defName}`}
|
|
onChange={(newDefSchema) => {
|
|
const newDefs = { ...defs };
|
|
newDefs[defName] = newDefSchema;
|
|
onChange(newDefs);
|
|
}}
|
|
rootSchema={rootSchema}
|
|
visibility={visibility}
|
|
/>
|
|
</div>
|
|
))}
|
|
|
|
{(!defs || Object.keys(defs).length === 0) && (
|
|
<p className="text-gray-500 italic">No definitions yet. Add one to reference it elsewhere in your schema.</p>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DefsEditor; |