@formitiva/react
v2.2.0
Published
Formitiva React adapter — components, hooks and registries
Maintainers
Readme
@formitiva/react
React adapter for Formitiva — build dynamic, schema-driven forms with a single component.
Features
- Single component — render any form from a JSON schema with
<Formitiva /> - 25+ built-in field types — text, email, phone, dropdown, date, file, rating, slider, unit values, and more
- Dynamic validation —
onEdit,onBlur, oronSubmissionmodes with built-in and custom validators - Conditional visibility — show/hide fields based on other field values via parent-child relationships
- Computed values — derive field values from other fields automatically
- Plugin system — register custom components, validators, submission handlers, and visibility rules
- Theming — CSS variable-based theming with light/dark support
- Localization — 29+ languages with CDN-based translation loading
- TypeScript — fully typed API
Installation
npm install @formitiva/react
# or
pnpm add @formitiva/reactPeer dependencies: react >=17, react-dom >=17
Quick Start
import { Formitiva } from "@formitiva/react";
const definition = {
name: "contactForm",
version: "1.0.0",
displayName: "Contact Form",
properties: [
{ name: "fullName", displayName: "Full Name", type: "text", defaultValue: "", required: true },
{ name: "email", displayName: "Email", type: "email", defaultValue: "", required: true },
{ name: "message", displayName: "Message", type: "multiline", defaultValue: "" },
],
};
const handleSubmit = (_def, _instanceName, values) => {
console.log("Submitted:", values);
return undefined;
};
export default function App() {
return <Formitiva definitionData={definition} onSubmit={handleSubmit} />;
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| definitionData | string \| object \| FormitivaDefinition | — | Form schema (JSON string, object, or typed definition) |
| instance | FormitivaInstance | — | Optional saved instance with pre-filled values |
| language | string | "en" | Language code for localization |
| theme | string | "light" | Theme name ("light" or "dark") |
| fieldValidationMode | FieldValidationMode | "onEdit" | When to validate: "onEdit", "onBlur", or "onSubmission" |
| displayInstanceName | boolean | true | Show an editable instance name field |
| onSubmit | FormSubmissionHandler | — | Callback on form submission |
| onValidation | FormValidationHandler | — | Cross-field validation callback |
| className | string | — | Additional CSS class for the container |
| style | CSSProperties | — | Inline styles for the container |
Advanced Layouts
Pass layout to let the React app choose nav, tab, or wizard presentation while the JSON schema remains focused on field data. The same definitionData can be rendered as a default form, a left-nav form, tabs, or wizard steps.
import { Formitiva } from "@formitiva/react";
const definition = {
name: "profile",
version: "1.0.0",
properties: [
{ name: "firstName", type: "text", displayName: "First Name", required: true },
{ name: "lastName", type: "text", displayName: "Last Name", required: true },
{ name: "email", type: "email", displayName: "Email", required: true },
{ name: "newsletter", type: "switch", displayName: "Newsletter" },
],
};
const tabLayout = {
name: "profileTabs",
type: "tab" as const,
displayName: "Profile Tabs",
defaultValue: "personal",
sections: [
{ label: "Personal", name: "personal", props: ["firstName", "lastName"] },
{ label: "Contact", name: "contact", props: ["email", "newsletter"] },
],
};
export default function App() {
return <Formitiva definitionData={definition} layout={tabLayout} />;
}Layout types:
| Type | Behavior |
|---|---|
| "nav" | Left-side navigation; each item renders its section fields |
| "tab" | Tab buttons above the form; switching tabs changes the active section |
| "wizard" | Step-by-step flow; Next is disabled while the current step has errors |
Each sections[].props entry must match field name values from the schema. definition.layoutRef and registerLayout() still work as a compatibility fallback, but new React code should pass layout directly.
Hooks
| Hook | Description |
|---|---|
| useFormitivaContext() | Access the current form context (language, theme, t, etc.) |
| useFieldValidator(field) | Returns a validation function respecting the current validation mode |
| useDebouncedCallback(fn, wait) | Debounced callback with leading/trailing options |
| useUncontrolledValidatedInput(props) | Manages uncontrolled inputs with validation and DOM sync |
| useDropdownPosition(ref) | Calculates safe popup positioning for dropdowns |
| useUnitValueField(props) | Manages unit value state with normalization |
Extending
Custom Components
import { registerComponent } from "@formitiva/react";
registerComponent("my-custom-field", MyCustomFieldComponent);Custom Validators
import { registerFieldValidator, registerTypeValidator } from "@formitiva/react";
// Per-definition field validator
registerFieldValidator("myForm", "validateAge", (fieldName, value, t) => {
if (Number(value) < 18) return t("Must be at least 18");
return undefined;
});
// Global type validator
registerTypeValidator("currency", (field, input, t) => {
if (Number.isNaN(Number(input))) return t("Must be a valid number");
return undefined;
});Plugins
import { registerPlugin } from "@formitiva/react";
registerPlugin({
name: "my-plugin",
version: "1.0.0",
components: { "my-field": MyFieldComponent },
fieldTypeValidators: { "my-field": myValidator },
});Themes
Import a built-in theme CSS file from @formitiva/core:
import "@formitiva/core/themes/material-dark.css";Or customize via CSS variables:
:root {
--formitiva-color-primary: #3b82f6;
--formitiva-color-error: #ef4444;
--formitiva-border-radius: 8px;
}Links
License
MIT
