Components

The package provides pre-built form elements with validation and styling via Shadcn UI.

Available Elements

Import from @schema-engine/forms-react/registrations:

import {
	InputElementRegistration,
	TextareaElementRegistration,
	CheckboxElementRegistration,
	RadioElementRegistration,
	SelectElementRegistration,
	SwitchElementRegistration,
	NumberElementRegistration,
	ArrayElementRegistration,
	FieldSetRegistration,
	SubmitButtonElementRegistration,
} from '@schema-engine/forms-react/registrations';
ElementDescription
inputText, email, password, tel, url inputs
textareaMulti-line text input
checkboxSingle checkbox or checkbox group
radioRadio button group
selectDropdown select
switchToggle switch
numberNumber input with increment/decrement
arrayDynamic array of form elements
fieldsetGroup of related form elements
submit-buttonForm submission button

Registration System

Import only what you need for tree-shaking:

import { createReactFormComposer } from '@schema-engine/forms-react';
import {
	InputElementRegistration,
	CheckboxElementRegistration,
	SelectElementRegistration,
} from '@schema-engine/forms-react/registrations';
 
const engine = createReactFormComposer()
	.addElement(InputElementRegistration)
	.addElement(CheckboxElementRegistration)
	.addElement(SelectElementRegistration)
	.build();

Element Configuration

Input Field

{
	"$type": "input",
	"id": "email",
	"name": "email",
	"label": "Email Address",
	"inputType": "email",
	"placeholder": "[email protected]",
	"rules": [
		{ "rule": "required", "message": "Email is required" },
		{ "rule": "email", "message": "Invalid email format" }
	]
}

Select Field

{
	"$type": "select",
	"id": "country",
	"name": "country",
	"label": "Country",
	"options": [
		{ "value": "us", "label": "United States" },
		{ "value": "ca", "label": "Canada" },
		{ "value": "uk", "label": "United Kingdom" }
	],
	"rules": [
		{ "rule": "required", "message": "Please select a country" }
	]
}

Grid Layout

Elements support responsive grid layouts:

{
	"id": "step-1",
	"grid": {
		"columns": 12,
		"gap": "1rem"
	},
	"elements": [
		{
			"$type": "input",
			"id": "firstName",
			"name": "firstName",
			"label": "First Name",
			"grid": { "column": "1 / 7" }
		},
		{
			"$type": "input",
			"id": "lastName",
			"name": "lastName",
			"label": "Last Name",
			"grid": { "column": "7 / 13" }
		}
	]
}

Creating a Custom Component

Step 1: Define Your Component

Use useControlledFormElement to integrate with the form:

import { useControlledFormElement } from '@schema-engine/forms-react';
 
export function CustomDatePicker(config: FormEngine.ElementConfig) {
	const {
		value,
		error,
		onChange,
		onBlur,
		fieldProps,
		labelProps,
		errorProps,
		containerStyles,
	} = useControlledFormElement(config);
 
	return (
		<div style={containerStyles}>
			<label {...labelProps}>{config.label}</label>
			<DatePicker
				{...fieldProps}
				selected={value}
				onChange={onChange}
				onBlur={onBlur}
			/>
			{errorProps && <span {...errorProps}>{error}</span>}
		</div>
	);
}

Step 2: Create Schema

import { z } from 'zod';
import { BaseElementConfigSchema } from '@schema-engine/forms/schemas';
 
export const CustomDatePickerConfigSchema = BaseElementConfigSchema.extend({
	$type: z.literal('custom-date-picker'),
	minDate: z.string().optional(),
	maxDate: z.string().optional(),
});

Step 3: Create Registration

import type { ElementRegistration } from '@schema-engine/forms';
 
export const CustomDatePickerRegistration: ElementRegistration = {
	$type: 'custom-date-picker',
	schema: CustomDatePickerConfigSchema,
	metadata: {
		name: 'Custom Date Picker',
		description: 'Date selection with custom styling',
		category: 'input',
	},
	render: CustomDatePicker,
};

Step 4: Register with Engine

const engine = createReactFormComposer()
	.addElement(CustomDatePickerRegistration)
	.build();

Step 5: Use in Form Config

{
	"$type": "custom-date-picker",
	"id": "birthdate",
	"name": "birthdate",
	"label": "Date of Birth"
}