Skip to content

Form OS — Capabilities

@jayoncode/form-intelligence is a headless form workflow engine — an operating system for forms. You pick the features you need; the engine centralizes validation, formatting, conditional logic, business rules, autosave, drafts, submission, and integrations while you keep full control of UI.

Previous: Core concepts · Next: Validation

One sentence

Form Intelligence manages everything that happens before, during, and after form submission — not just validation.

Status legend

BadgeMeaning
SHIPPEDAvailable today
PARTIALFoundation shipped; polish or integration pending
PLANNEDOn the roadmap

Core lifecycle

1. Form state management — SHIPPED

One instance owns values, errors, loading, dirty, and touched state.

ts
const form = createForm({
  initialValues: { email: "" },
  // Optional: declarative listeners (same store as form.subscribe; until destroy)
  subscribe: (form) => {
    syncUi(form.state);
  },
});

form.state.values;
form.state.errors;
form.state.isSubmitting;
form.state.isDirty;

State explorer →

2. Validation engine — SHIPPED

Declarative schema — no manual if (!email.includes("@")). On DOM-backed forms, Phase 1 HTML attributes (required, minlength, pattern, type="email"|"url", …) are imported into the same engine on attach (Field > Schema > HTML).

ts
createForm({
  schema: { email: { required: true, type: "email" } },
});
html
<!-- Or zero JS validators — attributes alone: -->
<input name="email" required type="email" />

Validation guide → · HTML constraints playground →

3. Custom validation — SHIPPED

Encode business rules in the schema or validator list.

ts
username: {
  validate(value) {
    return value !== "admin" || "Username already taken";
  },
}

4. Async validation — SHIPPED

Debounced onChange checks, per-field form.state.fieldMeta[path].isValidating for "Checking…" UI.

ts
username: {
  async validate(value) {
    const exists = await api.exists(value);
    return !exists || "Username already exists";
  },
}

Validation playground →


Input transformation

5. Formatting engine — SHIPPED

Presets: philippine-phone, credit-card, plus custom format / parse hooks.

Formatters →

5b. Transform pipeline — SHIPPED

Inbound stages before validation (trim / normalize / sanitize / parse):

ts
form.field("name", { transform: { trim: true, normalize: true } });
form.transform("code").pipe((v) => String(v).toUpperCase());

Import helpers from @jayoncode/form-intelligence/transform.


Conditional logic and rules

6. Conditional logic — SHIPPED

Show, hide, require, and enable fields based on other values — no scattered useEffect.

ts
import { createForm, when } from "@jayoncode/form-intelligence";

createForm({
  initialValues: { customerType: "Personal", companyName: "" },
  rules: [when("customerType").equals("Business").show("companyName")],
});

Wrap fields for DOM hide/show:

html
<div data-form-intelligent-field="companyName">
  <label>Company Name</label>
  <input name="companyName" />
</div>

Read presentation without digging into snapshots:

ts
form.getPresentation("companyName").field.visible;
form.field("companyName").ui.visible;
form.getPresentation().formUi.submitDisabled;

Import helpers from @jayoncode/form-intelligence/presentation when needed.

Rules guide →

7. Enable / disable — SHIPPED

ts
when("country").equals("Philippines").enable("province");

8. Required / optional — SHIPPED

ts
when("customerType").equals("Business").require("taxNumber");

9. Field dependency — SHIPPED

ts
when("country").changes(loadProvinces).populate("province");

// Structural cascade (clear children on parent change)
createForm({
  dependencies: { province: ["country"], city: ["province"] },
});

Dependencies playground → · Rules guide →

10. Calculations — SHIPPED

ts
form.calculate("total", ({ values }) => values.price * values.quantity);

form
  .calculate("total")
  .from("price", "quantity")
  .compute(({ get }) => Number(get("price")) * Number(get("quantity")));

Calculations guide → · Playground →

25. Business rule engine — SHIPPED

ts
form
  .when("loanAmount")
  .greaterThan(500_000)
  .then((ctx) => {
    ctx.show("managerApproval");
    ctx.require("managerApproval");
    ctx.disableSubmit();
  });

Rules playground →


Workflow

11. Wizard — SHIPPED

Multi-step forms with per-step validation, branching (when / next / canLeave / canEnter), goTo modes, and optional persistStepInDraft.

Workflow guide →

12. Progress — SHIPPED

form.state.workflow.progress — percentage and step navigation built in.

13. Autosave — SHIPPED

ts
workflow: { autosave: { enabled: true, debounceMs: 5000, onSave } }

14. Draft recovery — SHIPPED

form.saveDraft(), form.restoreDraft({ force?, prompt?, merge? }), restore on reload, optional promptOnRestore + envelopes/migrateDraft.

15. Offline queue — SHIPPED

workflow.offlineQueuemaxItems / overflow, idempotencyKey, onConflict, form.flushOfflineQueue() on reconnect.

Submission playground →


Submission and change tracking

16. Submission engine — SHIPPED

Validate → loading → disable button → API → success/error → re-enable. submitPhase machine + form.useMiddleware onion (same stack as plugin hooks).

Submission guide →

17. Dirty tracking — SHIPPED

form.isDirty() for leave-page guards.

18. Undo / redo — SHIPPED

form.undo() / form.redo() with value history stack.

19. Changed fields — SHIPPED

form.changedFields() returns paths that differ from initial values.

State guide →


Integrations

20. Browser session — SHIPPED

ts
import { createBrowserLifecyclePlugin } from "@jayoncode/form-intelligence/plugins";

form.use(createBrowserLifecyclePlugin({ saveDraftOnHidden: true }));

Saves draft when the tab is hidden.

21. Keyboard shortcuts — SHIPPED

workflow.keyboard or createKeyboardPlugin() — Ctrl+S save, Ctrl+Enter submit.

Integrations guide → · Playground →

22. Analytics — SHIPPED

form.getAnalytics() — errors by field, field views, drop-off, timings. Path allow/deny; never snapshots values. Not a product analytics SDK.

23. Plugin system — SHIPPED

createForm({ plugins }) / form.use(plugin) / registerPlugin(), hook bus, error isolation (onPluginError), version / engines metadata, PLUGIN_PIPELINE_STAGES.

Plugins guide → · Author guide →

24. React adapter — SHIPPED

tsx
import { useForm } from "@jayoncode/form-intelligence-react";

const form = useForm({ schema: { email: "email" } });
// form.controller · form.fieldController · aria on form.field()

Vue / Angular packages ship the same controller contract as React (controller, fieldController, focusFirstInvalid).

Adapters guide →

26. Controllers + accessibility — SHIPPED

createFormController(form), field.aria / setAriaIds, focusFirstInvalid, @jayoncode/form-intelligence/accessibility.

27. DevTools — SHIPPED (optional subpath)

ts
import { enableFormDevTools, getFormDevTools } from "@jayoncode/form-intelligence/devtools";

Inspector: events, validation, workflow, plugins, performance marks. Not pulled into the core-login bundle.

Integrations → · Playground →


How it fits together

USER TYPES → State Updates → Validation / Formatting / Rules
          → Update State → Re-render → Submit → Submission Engine

Next steps

GoalGuide
Get startedTutorial
Conditional fieldsRules
Derived valuesCalculations
Snapshots / undoState
Session / keyboardIntegrations
Controllers / a11yAdapters
Bundle / timingPerformance
Engineering roadmap002-form-os-capabilities

JOC — headless @jayoncode/* TypeScript libraries. Docs sync from package source via TypeDoc and sync scripts.