0.0.0 • Published 2d ago
form-os
Licence
—
Version
0.0.0
Deps
0
Size
134 kB
Vulns
0
Weekly
0
form-os
A small, cross-framework form config library.
@form-os/core— dependency-free config parser, dependency engine, and validation helpers.@form-os/react—react-hook-formadapter with tree-shakeable field components.@form-os/schema— JSON Schema and TypeScript types for form configs.@form-os/svelte— placeholder for a future Svelte adapter.
Install
pnpm add @form-os/core @form-os/react react-hook-form
# optional
pnpm add @form-os/schema
React and react-hook-form are peer dependencies of @form-os/react.
Define a form config
import type { FormConfig } from '@form-os/core';
const config: FormConfig = {
title: 'Contact',
submitLabel: 'Send',
fields: [
{ name: 'name', type: 'text', label: 'Name', rules: { required: true } },
{ name: 'email', type: 'email', label: 'Email', rules: { required: true } },
{
name: 'reason',
type: 'select',
label: 'Reason',
options: [
{ label: 'Feedback', value: 'feedback' },
{ label: 'Support', value: 'support' },
],
},
{
name: 'details',
type: 'textarea',
label: 'Details',
dependencies: [
{ name: 'reason', value: 'support', type: 'show' },
],
},
],
};
Use with React
import { FormProvider } from '@form-os/react';
import { DefaultField, useFormConfig } from '@form-os/react/fields';
function MyForm() {
const { handleSubmit, fields, ...form } = useFormConfig(config);
const onSubmit = (data: any) => console.log(data);
return (
<FormProvider {...form}>
<form onSubmit={handleSubmit(onSubmit)}>
{fields.map((field) => (
<DefaultField key={field.name} field={field} />
))}
<button type="submit">Send</button>
</form>
</FormProvider>
);
}
Custom field components
import { Field, useFormConfig } from '@form-os/react';
import { TextField, defaultComponents } from '@form-os/react/fields';
const components = {
...defaultComponents,
text: (props) => (
<div>
<label>{props.fieldConfig.label}</label>
<TextField {...props} />
{props.error && <span>{props.error.message}</span>}
</div>
),
};
<Field field={config.fields[0]} components={components} />
Use the core without React
import { normalizeConfig, createDefaultValues, getFieldState } from '@form-os/core';
const { fields } = normalizeConfig(config);
const defaults = createDefaultValues(fields);
const state = getFieldState(fields[0], defaults);
// state.visible, state.required, state.disabled, state.defaultValue
Validate against the JSON schema
import { schema } from '@form-os/schema';
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(schema);
if (!validate(config)) {
console.error(validate.errors);
}
Scripts
pnpm install
pnpm build # build every package
pnpm test # run the test suite
pnpm typecheck # run tsc --noEmit in every package