A form builder library for React applications.
npm install @khamphamoi/form-builderA type-safe, reactive form library for React with declarative conditional logic.
Form state lives independently from React components. Fields subscribe to only the data they need, minimizing re-renders.
``typescript
// Your type definition (compile-time)
type Address = { street: string; city: string }
type Form = { user: { name: string; address: Address } }
// Runtime storage (always flat)
{
"user.name": "John",
"user.address.street": "123 Main",
"user.address.city": "NYC"
}
`
Why? Simple, predictable storage while preserving type safety and autocomplete.
Components subscribe to specific fields. Changing user.name doesn't re-render user.address.city.
Express "when X, then Y" as data structures, not imperative code:
`typescript`
when
- v0: Basic forms with validation
- v1: Adds conditional show/hide/set logic
---
`typescript
import { NdcForm, useFormField } from "@khamphamoi/form-builder";
type LoginForm = {
email: string;
password: string;
};
function EmailField() {
const field = useFormField
name: "email",
initialValue: "",
validators: [
(value) => (!value ? "Email required" : null),
(value) => (!value?.includes("@") ? "Invalid email" : null),
],
});
return (
function App() {
return (
{/ more fields... /}
);
}
`
`typescript
import { NdcForm, when, v } from "@khamphamoi/form-builder";
type ShippingForm = {
country: string;
state?: string;
province?: string;
};
const conditions = [
// Show 'state' only for US
when
.show((x) => x.state)
.hide((x) => x.province)
.toRules(),
// Show 'province' only for Canada
when
.show((x) => x.province)
.hide((x) => x.state)
.toRules(),
].flat();
function App() {
return (
);
}
`
---
Access nested fields using dot notation:
`typescript
type Form = {
user: {
profile: {
name: string;
};
};
};
// Field path: "user.profile.name"
const field = useFormField