@marianmeres/questionnaire
v1.1.1
Published
[](https://www.npmjs.com/package/@marianmeres/questionnaire) [](https://jsr.io/@marianmeres/questionnaire) [ from plain, serializable definitions — with per-field validation and conditional visibility. Not a form builder — the layer a form builder would sit on top of. Zero dependencies.
What you get
- Definition format — plain JSON:
steps[]→fields[]with semantic field types (text,number,boolean,choice,choices,date), JSON-Schema-shaped validation rules (minLength,pattern,minimum, ...) and conditional visibility (showIf) in the condition-builder dump format. Authoring or generating configs elsewhere? See the field-by-field config authoring guide. - Stateless helpers — pure
(config, values)functions:validateConfig,validateAnswers(e.g. server-side re-validation of a submission),resolveVisibility,extractAnswers,evaluateCondition. - Runtime engine —
createQuestionnaire(): a small reactive state container (Svelte store contract) owning values, touched flags, errors, visibility and per-stepcompletegating.
Installation
deno add jsr:@marianmeres/questionnairenpm install @marianmeres/questionnaireUsage
import { createQuestionnaire } from "@marianmeres/questionnaire";
const q = createQuestionnaire({
steps: [
{
id: "lifestyle",
title: "Lifestyle",
fields: [
{
name: "diet",
type: "choice",
title: "Any diet or dietary restrictions?",
description: "Including food allergies, intolerances and veganism.",
options: [
{ value: "yes", label: "yes" },
{ value: "no", label: "no" },
],
ui: { control: "radio" }, // opaque hint — the engine never reads it
},
{
name: "diet_detail",
type: "text",
title: "Please specify",
required: true,
// show only when diet === "yes"
showIf: [{
expression: { key: "diet", operator: "eq", value: "yes" },
operator: "and",
}],
validate: { maxLength: 500 },
},
],
},
],
});
q.subscribe(({ steps, fields, valid, complete }) => {
// render... (or use $q auto-subscription in Svelte)
});
q.setValue("diet", "yes");
q.get().fields.diet_detail.visible; // true
q.setValue("diet_detail", "vegan");
q.markTouched("diet_detail"); // typically on blur — reveals errors in your UI
q.dump(); // { diet: "yes", diet_detail: "vegan" }Semantics worth knowing
- "Only filled answers are submitted" —
requireddefaults tofalse;dump()/state.answerscontain only visible and filled fields.falseand0count as answers;"",[],null,undefineddo not. textis trimmed — leading/trailing whitespace is stripped before validating and extracting, so" "reads as unanswered and a padded answer is submitted without the padding. The raw value stays in state while editing (so typing a trailing space works); only the answer is trimmed. Other types are untouched.- Hidden ≠ deleted — a hidden field's value survives in state (flip the condition back and it reappears) but the field is never validated and never appears in answers.
- Conditions see effective answers — hidden or unfilled fields read as
undefinedinshowIfevaluation, so hiding cascades correctly through chains. CircularshowIfdependencies are rejected byvalidateConfig. - Required-empty is a validation error — a pristine questionnaire with required
fields is not
valid; UIs typically reveal an error only once its field istouched(that is whattouchedis for). Gate forward navigation onStepState.complete. - The engine does not navigate — pair it with
@marianmeres/wizard (or a few lines of
app code) and gate
next()on the current step'scomplete. - Conditions are authorable as strings —
showIftakes the parsed AST, so you can write"diet:yes"and convert it at authoring time with @marianmeres/condition-parser (the engine itself stays zero-dependency).
Examples
Working browser examples built with
@marianmeres/vanilla live in
example/:
deno task example:build
deno task example:serve
# open http://localhost:8000Documentation
- API.md — complete public API reference.
- Config authoring guide — self-contained,
field-by-field reference aimed at whoever produces the config JSON (e.g. a
separate backend team): every type, field, validation rule,
showIfoperator, and the exact shape of the submitted answers. - example/ — runnable browser demos.
