@sometic/forms
v1.1.3
Published
Framework-independent form engine, fields and validation orchestration for Sometic.
Maintainers
Readme
@sometic/forms
Framework-independent form engine for field registration, validation orchestration, drafts, steps, and feedback.
@sometic/forms owns form state: values, field meta (dirty/touched/visited/invalid), submit handling, server error injection, field arrays, multi-step definitions, and draft persistence helpers. It pairs with @sometic/validation for native validators and schema adapters instead of baking Yup or Zod into the core.
Sometic treats forms as portable application behavior, not a React Hook Form clone tied to one renderer. Controllers are disposable, SSR-safe to construct, and easy to bind from Vanilla, Web Components, or thin framework hooks. Accessibility helpers (focusFirstInvalid, announceFormErrors) and feedback builders keep invalid submit UX consistent across stacks.
Standout exports include createForm, createFieldArrayController, createDraftController with memory/localStorage draft storage, createFormSteps, FormData bridges (valuesToFormData, formDataToValues), and feedback helpers (createValidationFeedback, feedbackAttributes). Subpaths such as @sometic/forms/drafts, @sometic/forms/steps, @sometic/forms/a11y, and @sometic/forms/server keep bundles intentional.
This package sits on @sometic/core and @sometic/validation. UI wiring often comes from @sometic/dom / @sometic/elements, and session-safe composition can use @sometic/app-shell. See the introduction and forms overview.
Install
pnpm add @sometic/formsnpm install @sometic/formsyarn add @sometic/formsUsage
Create a form with field validators and submit handlers:
import { createForm } from "@sometic/forms";
import { email, minLength, required } from "@sometic/validation";
const form = createForm({
defaultValues: { email: "", password: "" },
});
form.register("email", {
validators: [required("Email is required"), email()],
});
form.register("password", {
validators: [required("Password is required"), minLength(8)],
});
const onSubmit = form.handleSubmit({
onValid: async (values) => {
await fetch("/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(values),
});
},
onInvalid: () => {
console.log(form.getIssues());
},
});
await onSubmit();Persist drafts and build FormData for native multipart posts:
import { createDraftController, createMemoryDraftStorage, valuesToFormData } from "@sometic/forms";
const drafts = createDraftController({
key: "login-draft",
version: 1,
storage: createMemoryDraftStorage(),
getValues: () => form.getValues(),
setValues: (values) => {
for (const [path, value] of Object.entries(values)) {
form.setValue(path, value);
}
},
});
await drafts.save();
const body = valuesToFormData(form.getValues());CDN
Docs: https://sometic.dev/forms/.
Simple script
<script src="https://cdn.jsdelivr.net/npm/@sometic/[email protected]/dist/cdn/sometic-forms.iife.js"></script>
<script>
const form = SometicForms.createForm({ defaultValues: { email: "" } });
</script>Module script
<script type="module">
import { createForm } from "https://cdn.jsdelivr.net/npm/@sometic/[email protected]/dist/cdn/sometic-forms.esm.js";
const form = createForm({ defaultValues: { email: "" } });
</script>Peers / when not to use
Depends on @sometic/core and @sometic/validation. No framework peers.
Do not use @sometic/forms for server-state caching (that is @sometic/query) or session identity (@sometic/auth). If you only need one-off validators without form meta/submit orchestration, import @sometic/validation alone.
Docs
License
MIT
