GitHub

Schema Builder

Build the JSON Schema that drives a Retab extraction — the same editor used in the Retab dashboard.

The Schema Builder is the JSON Schema editor from the Retab dashboard: recursive fields, a type picker, enums, optional $defs / references, optional JSON mode, and live validation. It is a controlled component that edits the json_schema an extraction runs against and emits standard JSON Schema. The editor normalizes object properties as required; use nullable field types when a required field may return null.

items

Usage

Give the component your schema state and handle every edit through onValueChange:

import { useState } from "react";
import {
  SchemaBuilder,
  type ExtendedJSONSchema7,
} from "@/components/ui/schema-builder";
 
export function Example() {
  const [schema, setSchema] = useState<ExtendedJSONSchema7>({
    type: "object",
    properties: {},
    required: [],
  });
  return <SchemaBuilder value={schema} onValueChange={setSchema} />;
}

Read-only

Pass readOnly to render an existing schema as a static, non-editable summary — no type pickers, inline inputs, or row actions. Useful for review screens and run history.

invoice_number
The invoice identifier
string
issue_date
Date the invoice was issued
string
total
Total amount due
number
currency
Add description
multiple choice
paid
Add description
true/false

Definitions and features

Optional surfaces turn on through features (only definitions is on by default). definitions lets a schema reuse a shared shape through $defs and $ref; objectTemplates and importExport add reusable object templates and import/export actions, and jsonMode adds the Fields ⇄ JSON toggle. This example enables them all over a schema whose billing_address and shipping_address reference one address definition.

API Reference

PropTypeDescription
valueExtendedJSONSchema7The schema state.
onValueChange(schema: ExtendedJSONSchema7) => voidCalled with the next schema whenever the user edits it.
classNamestringOptional wrapper class name.
readOnlybooleanRenders the current schema without allowing edits.
view"fields" | "json"Controls the active view when JSON mode is enabled.
onViewChange(view: "fields" | "json") => voidCalled when the user switches between fields and JSON mode.
featuresSchemaBuilderFeaturesEnables optional surfaces: definitions, objectTemplates, jsonMode, and importExport.

Optional feature defaults are intentionally small: definitions is enabled, while objectTemplates, jsonMode, and importExport are disabled unless you turn them on.

Property Form

When you click a field's edit action, the Schema Builder opens an Edit Property dialog. The body of that dialog is PropertyForm — name, data type, type-specific options (enum values, array item type, $ref), nullable controls, and description. It edits a local draft and emits a single validated commit through onCommitPropertyDraft.

PropertyForm renders just the form (no dialog chrome), so the Schema Builder drops it into a <DialogContent> while you can reuse the same subcomponent in a popover or an inline panel.

Using Property Form standalone

PropertyForm does not own the parent schema. Pass the current property draft through propertyDraft, parent-local schema context through schemaContext, and persist changes in onCommitPropertyDraft.

import { useState } from "react";
 
import type { ExtendedJSONSchema7 } from "@/components/schema-editor/lib/json-schema-types";
import { PropertyForm } from "@/components/schema-editor/property-form/property-form";
 
export function Example() {
  const [property, setProperty] = useState<ExtendedJSONSchema7>({
    type: "string",
  });
  const [name, setName] = useState("currency");
  return (
    <PropertyForm
      propertyDraft={{ name, schemaNode: property }}
      schemaContext={{
        siblingNames: [],
        originalName: name,
        schemaDefinitions: {},
      }}
      submitLabel="Save"
      onCommitPropertyDraft={(next) => {
        setName(next.name);
        setProperty(next.schemaNode);
      }}
      onCancel={() => {}}
      onDelete={() => {}}
    />
  );
}

Property Form props

PropTypeDescription
propertyDraft{ name; schemaNode }The property draft to edit.
schemaContextPropertyFormSchemaContextParent-local validation names, original name, $defs, and optional command handler for definitions/templates.
onCommitPropertyDraft(next: { name; schemaNode }) => void | Promise<void>Called only after validation passes.
onCancel() => voidCalled on Cancel.
onDelete() => voidOptional. Shows the Delete Property action.
submitLabelstringSubmit button label. Defaults to "Save Changes".
mode"editable" | "readOnly" | "descriptionOnly"Defaults to "editable".

Source

schema-builder.tsx