Schema Reference

Complete reference for all TypeScript types exported by form-builder-types.

FormSchema

The root object passed to FormRenderer and emitted by FormBuilder.

FieldTypeDescription
id*stringUnique identifier for the form.
title*LocalizedStringForm heading, displayed above the fields.
descriptionLocalizedStringOptional subtitle shown below the title.
fields*FormFieldDefinition[]Ordered list of field definitions. Rendered in ascending order value.
submitLabelLocalizedStringSubmit button label. Defaults to "Submit".
settingsFormSchemaSettingsLayout and behavior overrides.

FormFieldDefinition

Defines a single field in the form. Each entry in FormSchema.fields conforms to this type.

FieldTypeDescription
id*stringInternal identifier for the field (used for selection/reordering in the builder). Falls back to this as the form data key when key is not set.
keystringStable, human-readable property name used as the form data key in the submitted object and JSON Schema. Not applicable to display-only fields (heading, paragraph, separator, pagebreak).
type*FormFieldTypeThe widget type. See Field Types below.
label*LocalizedStringVisible label for the field.
order*numberSort order. Fields are rendered in ascending order.
placeholderLocalizedStringInput placeholder text. Applies to text, email, tel, number, textarea.
descriptionLocalizedStringHelper text shown below the input.
requiredbooleanMarks the field as required. Adds JSON Schema required constraint.
defaultValueunknownInitial value pre-filled in the form.
optionsFormFieldOption[]Required for select and radio types.
validationFormFieldValidationValidation constraints. See Validation below.
conditionFormFieldConditionConditional display rule. Field is hidden unless the condition passes.

Field Types

The 10 input types, their JSON Schema mapping, and notes on behavior.

TypeWidgetJSON SchemaNotes
textInput (text)type: "string"General single-line text input.
numberInput (number)type: "number"Numeric input. Supports min/max validation.
emailInput (email)type: "string", format: "email"Validates email format automatically.
telInput (tel)type: "string"Phone number input with type="tel" for mobile keyboards.
selectSelect (dropdown)type: "string", enum: [...]Requires options. Uses shadcn Select component.
checkboxCheckboxtype: "boolean"Single boolean toggle. Submits true/false.
radioRadioGrouptype: "string", enum: [...]Requires options. Each option renders as a radio button.
dateInput (date)type: "string", format: "date"Native date picker. Submits ISO 8601 date string.
textareaTextareatype: "string"Multi-line text. Supports minLength/maxLength.
fileInput (file)type: "string", format: "data-url"File picker. Value is a base64 data URL.

Display fields — heading, paragraph and separator — render a heading, a paragraph (from label) and a divider. They collect no data and are excluded from submitted form data. pagebreak is a layout field that starts a new page; see Pages.

LocalizedString

LocalizedString is string | Record<string, string>. Use a plain string for single-language forms; use a locale map for multi-language forms.

// Plain string — always displayed as-is
label: "Full Name"

// Locale map — resolved at render time using the locale prop
label: { "en-US": "Full Name", "ko-KR": "이름", "ja-JP": "氏名" }

Resolution order: active locale → baseLocale → first available key → empty string.

Validation

The validation field accepts a FormFieldValidation object.

FieldTypeApplies toDescription
minLengthnumbertext, email, tel, textareaMinimum character count.
maxLengthnumbertext, email, tel, textareaMaximum character count.
minnumbernumberMinimum numeric value.
maxnumbernumberMaximum numeric value.
patternstringtext, telRegex pattern the value must match.
customRulestringall input typesKey referencing a validator registered via registerValidator.

Custom validators

Register a validator once (at app startup) and reference it by key in any field's validation.customRule.

import { registerValidator } from '@/lib/form-builder-types/validation';

// Register once (e.g. in a layout or provider)
registerValidator('no-profanity', (value) => {
  if (typeof value === 'string' && value.includes('badword')) {
    return 'Please keep it respectful.';
  }
});

// FormRenderer runs registered validators automatically for any field with
// validation: { customRule: 'no-profanity' }.
// For one-off checks, pass an RJSF customValidate function as well:
<FormRenderer
  schema={schema}
  locale="en-US"
  customValidate={(formData, errors) => errors}
/>

Conditions

Set condition on a field to make it conditionally visible based on another field's current value.

// Show "otherDetails" only when "topic" equals "other"
{
  id: 'otherDetails',
  type: 'textarea',
  label: 'Please describe',
  order: 5,
  condition: {
    field: 'topic',   // the field id to watch
    operator: 'eq',
    value: 'other',
  }
}

Operators

OperatorDescriptionvalue required?
eqStrict equality (===)Yes
neqStrict inequality (!==)Yes
gtGreater than. Numeric comparison.Yes
ltLess than. Numeric comparison.Yes
containsString includes the value.Yes
emptyField value is empty, null, or undefined.No
notEmptyField value is not empty.No

Values of hidden fields are left out of the data passed to onChange and onSubmit. Conditions can chain: if a field depends on one that is hidden, it is hidden too. When a field is shown again, the value the user typed earlier comes back.

Pages

Add a pagebreak field to split a long form into pages. Fields before the first break form page 1, and each break starts the next page. The break's label and description become that page's title and subtitle; an empty label falls back to the form title.

fields: [
  { id: 'name',  key: 'name',  type: 'text',  label: 'Name',  required: true, order: 0 },
  { id: 'p2',    type: 'pagebreak', label: 'Contact', order: 1 },
  { id: 'email', key: 'email', type: 'email', label: 'Email', required: true, order: 2 },
],
settings: { showProgressBar: true }
  • Next validates only the current page. Back never validates, and values are kept when moving between pages.
  • On submit, every visible field is validated again. If a field on an earlier page fails (for example, a condition made it required after that page was passed), the form goes back to that page and shows the error.
  • Submitted data stays flat — pages don't nest it. toJsonSchema and toUiSchema skip page breaks, so the JSON Schema of a paged form is the same as without pages.
  • Pages left empty, for example because every field on them is hidden by a condition, are skipped.

Settings

FormSchemaSettings is an optional object on the root FormSchema. Fields marked planned are part of the type, but FormRenderer does not act on them yet. Track progress in the changelog.

FieldTypeDefaultDescription
layoutplanned"vertical" | "horizontal""vertical"Controls label position relative to the input.
showProgressBarbooleanfalseMulti-page forms only. Shows a progress bar under the page counter.
nextLabelLocalizedString"Next"Multi-page forms only. Label of the button that goes to the next page.
backLabelLocalizedString"Back"Multi-page forms only. Label of the button that goes to the previous page.
successMessageplannedLocalizedString—Message shown after successful submission (if provided).