@haloform/core
v0.2.0
Published
Core engine for haloform — schema, types, store, validation
Maintainers
Readme
This is the core package of haloform. It contains the schema builders, store, validation engine, dependency resolution, and multi-step form logic — all in pure TypeScript with zero runtime dependencies.
For React hooks, install @haloform/react.
For React Native prop mappers, install @haloform/native.
Install
npm install @haloform/core @haloform/reactQuick Start
import { createForm, f } from "@haloform/core";
import { useForm } from "@haloform/react";
const loginSchema = createForm({
email: f.email({ required: true }),
password: f.text({ required: true, minLength: 8 }),
remember: f.checkbox({ default: false }),
});
function LoginForm() {
const { fields, handleSubmit } = useForm(loginSchema);
return (
<form onSubmit={handleSubmit((values) => console.log(values))}>
<input
value={fields.email.value}
onChange={(e) => fields.email.onChange(e.target.value)}
onBlur={fields.email.onBlur}
/>
{fields.email.error && <span>{fields.email.error}</span>}
<input
type="password"
value={fields.password.value}
onChange={(e) => fields.password.onChange(e.target.value)}
onBlur={fields.password.onBlur}
/>
<button type="submit">Sign in</button>
</form>
);
}Field Builders (f.*)
| Builder | Value Type | Extra Config |
|---|---|---|
| f.text() | string | minLength, maxLength, pattern |
| f.email() | string | Built-in email format validation |
| f.number() | number | min, max |
| f.checkbox() | boolean | — |
| f.select() | string | options (required) |
| f.radio() | string | options (required) |
| f.textarea() | string | minLength, maxLength |
| f.date() | string | — |
All builders accept: required, default, validate, dependsOn.
Features
| Feature | Description |
|---|---|
| Schema-driven | Define fields with f.text(), f.email(), f.select(), etc. |
| Built-in validation | Required, minLength, maxLength, min, max, email, pattern |
| Async validation | Debounced with AbortController — stale requests auto-cancel |
| Field dependencies | dependsOn for conditional visibility, dynamic options, cascading values |
| Multi-step forms | createMultiStepForm with per-step validation and navigation |
| Cross-field validation | Form-level validate(values) for password confirmation, etc. |
| Full type inference | Schema infers { email: string, age: number, agreed: boolean } |
| Zero dependencies | Pure TypeScript, ~5KB gzipped |
Async Validation
const schema = createForm({
username: f.text({
required: true,
validate: async (value, signal) => {
const res = await fetch(`/api/check-username?u=${value}`, { signal });
const { available } = await res.json();
return available ? true : "Username is taken";
},
}),
});The async validator receives an AbortSignal — if the user types again before the previous check completes, it's automatically cancelled.
Field Dependencies
const schema = createForm({
country: f.select({ options: ["US", "PE", "PT"], required: true }),
state: f.select({
options: [],
dependsOn: {
country: (value) => ({
visible: value === "US",
options: value === "US" ? ["CA", "NY", "TX"] : [],
}),
},
}),
});Multi-Step Forms
import { createMultiStepForm, f } from "@haloform/core";
const checkoutSchema = createMultiStepForm([
{
name: "Shipping",
fields: {
name: f.text({ required: true }),
address: f.text({ required: true }),
},
},
{
name: "Payment",
fields: {
card: f.text({ required: true, pattern: /^\d{16}$/ }),
cvv: f.text({ required: true, minLength: 3 }),
},
},
]);Architecture
@haloform/core Pure TypeScript, zero deps
├── schema.ts Field builders (f.*) + createForm
├── types.ts Full type system with inference
├── store.ts Subscribable state management
├── validation.ts Sync/async + debounce + abort
├── dependencies.ts Inter-field dependency resolution
└── multistep.ts Multi-step navigation + per-step validationFull Documentation
See the full documentation and examples on GitHub.
License
MIT — Made with care by Angel Orellana
