Skip to content

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
}
ExportDescription
createWizardState(steps, index?)Initial state; index is clamped into range
validateStep(step, data){ valid, errors } for one step's fields
canGoNext / canGoPrevWhether a move is possible
goNext / goPrevMove 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.

Released under the MIT License.