Files
json-schema-editor/src/components/DefsEditor.tsx
2025-05-05 22:35:22 +01:00

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;