Multi-step wizard
A framework-agnostic state machine over grouped fields. State is immutable: every navigation returns a new object.
ts
import {
createWizardState,
validateStep,
goNext,
goPrev,
isStepCompleted,
} from '@dynamic-field-kit/core';
let wizard = createWizardState([
{ id: 'account', title: 'Account', fields: accountFields },
{ id: 'profile', title: 'Profile', fields: profileFields },
]);
const { valid, errors } = validateStep(wizard.currentStep, data);
if (valid) {
wizard = goNext(wizard); // records the step it leaves in completedSteps
}| Export | Description |
|---|---|
createWizardState(steps, index?) | Initial state; index is clamped into range |
validateStep(step, data) | { valid, errors } for one step's fields |
canGoNext / canGoPrev | Whether a move is possible |
goNext / goPrev | Move one step; returns the same object when it cannot, so === detects a no-op |
goToStep(state, index) | Jump anywhere (clamped); does not mark anything completed |
markStepCompleted(state, index?) | Record a step as done, defaulting to the current one |
isStepCompleted(state, index) | For rendering a step indicator |
Each step is a FormStep, and WizardState is what every helper above takes and returns:
ts
export interface FormStep {
id: string;
title: string;
description?: string;
fields: FieldDescription[];
}
export interface WizardState {
currentStepIndex: number;
totalSteps: number;
isFirstStep: boolean;
isLastStep: boolean;
currentStep: FormStep;
steps: FormStep[];
completedSteps: number[];
}goNext does not validate — call validateStep yourself so a "save draft and come back" flow stays possible.