@ht-rnd/json-schema-editor
v2.0.4
Published
Headless JSON Schema Editor - provides hooks and utilities for building JSON Schema editors
Maintainers
Readme
@ht-rnd/json-schema-editor
A powerful headless JSON Schema editor for React. Build fully customized editors with complete UI control while leveraging battle-tested logic, validation, and state management.
Headless Architecture: Core logic via npm + optional copy-paste UI components. Use our pre-built Shadcn/ui components or build your own interface.
Features
- Multi-Draft Support - Draft-07, 2019-09, and 2020-12 with automatic detection via
$schemaURI - All Types - string, number, integer, boolean, object, array, $ref
- Nested Schemas - Unlimited depth for objects and arrays
- $defs / definitions Support - Reusable definitions with
$ref; emits the correct key per draft - Validation - AJV-powered real-time draft-aware validation
- Combinators - allOf, anyOf, oneOf, not
- TypeScript - Full type safety
- Headless - Zero UI dependencies in core
Installation
npm install @ht-rnd/json-schema-editorOptional UI components: Copy components/ui/ from this repo to your project. Requires Radix UI and Tailwind CSS.
Quick Start
Option 1: Pre-built Components
import { JsonSchemaEditor } from "@/components/ui/json-schema-editor";
function App() {
return (
<JsonSchemaEditor
rootType="object"
onChange={(schema) => console.log(schema)}
/>
);
}Option 2: Headless Hook
import { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";
import { FormProvider } from "react-hook-form";
function App() {
const editor = useJsonSchemaEditor({
rootType: "object",
onChange: (schema) => console.log(schema),
});
return (
<FormProvider {...editor.form}>
<button onClick={editor.addField}>Add Field</button>
{editor.fields.map((field, index) => (
<div key={field.id}>
<input value={field.key} />
<button onClick={() => editor.removeField(index)}>Remove</button>
</div>
))}
<pre>{JSON.stringify(editor.schema, null, 2)}</pre>
</FormProvider>
);
}API Reference
useJsonSchemaEditor(options)
Main hook for editor state management.
Options:
{
rootType?: "object" | "array"; // Default: "object"
defaultValue?: JSONSchema; // Load existing schema
onChange?: (schema: JSONSchema) => void;
}Returns:
{
// State
schema: JSONSchema;
errors: SchemaError[] | null; // null when valid
fields: FieldItem[];
definitions: DefinitionItem[];
form: UseFormReturn;
settingsState: { isOpen: boolean; fieldPath: string | null };
// Actions
addField: () => void;
removeField: (index: number) => void;
addDefinition: () => void;
removeDefinition: (index: number) => void;
updateReferences: (oldKey: string, newKey: string | null) => void; // update $ref strings when a definition key changes
openSettings: (path: string) => void;
closeSettings: () => void;
handleTypeChange: (path: string, type: string) => void;
addNestedField: (parentPath: string) => void;
reset: () => void;
}JsonSchemaEditor Component Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| rootType | "object" \| "array" | "object" | Root schema type |
| defaultValue | JSONSchema | - | Initial schema to load |
| onChange | (schema) => void | - | Callback on schema change |
| readOnly | boolean | false | View-only mode |
| showOutput | boolean | true | Show/hide JSON output panel |
| defaultOutputCollapsed | boolean | false | Start the JSON output panel collapsed |
| className | string | - | Additional CSS classes |
Exports
// Main hook
export { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";
// Types
export type { JSONSchema, FieldItem, DefinitionItem, UseJsonSchemaEditorReturn };
// Utilities (all draft-aware: select AJV instance / emit correct defs key based on $schema)
export { validateSchema, formToSchema, schemaToForm };
// Constants
export { SCHEMA_TYPES, STRING_FORMATS, NUMBER_FORMATS, INTEGER_FORMATS };Examples
Load Existing Schema
const editor = useJsonSchemaEditor({
rootType: "object",
defaultValue: {
type: "object",
properties: {
username: { type: "string", minLength: 3 },
email: { type: "string", format: "email" },
age: { type: "integer", minimum: 18 }
},
required: ["username", "email"]
}
});Validate Data Against Schema
import Ajv from "ajv";
const ajv = new Ajv();
const validate = ajv.compile(editor.schema);
const valid = validate({ username: "john", email: "[email protected]" });
if (!valid) console.log(validate.errors);Persist Schema Changes
const editor = useJsonSchemaEditor({
onChange: (schema) => {
localStorage.setItem("schema", JSON.stringify(schema));
// Or send to API
}
});Contributing
Contributions welcome! See GitHub for issues and PRs.
git clone https://github.com/ht-rnd/json-schema-editor.git
npm install
npm test
npm run demoLicense
Apache-2.0 © [HT-RND]
See LICENSE for more details.
