@matthew.ngo/reform
Version:
A flexible and powerful React form management library with advanced validation, state observation, and multi-group support
246 lines (245 loc) • 8.35 kB
TypeScript
/**
* Defines types and interfaces for multi-step form wizard functionality.
* This module provides the type definitions for managing step-based forms
* with navigation, validation, and completion tracking.
*/
import { FormGroup } from '../../core/form/form-groups';
/**
* Represents a single step in a multi-step form
*
* @template T - The type of form data
*/
export interface FormStep<T> {
/** Unique identifier for the step */
id: string;
/** Display name of the step */
name: string;
/** Optional description of what this step is for */
description?: string;
/**
* Array of group indices that belong to this step
* These indices correspond to the groups in the Reform form
*/
groupIndices: number[];
/**
* Optional validation function to determine if the step is valid
* If not provided, the step will be considered valid if all its groups pass their schema validation
*
* @param groups - The form groups associated with this step
* @returns Whether the step is valid
*/
validate?: (groups: FormGroup<T>[]) => boolean;
/**
* Optional function to determine if the step should be enabled
* If not provided, the step will be enabled if all previous steps are completed
*
* @param groups - All form groups
* @param completedSteps - Array of step IDs that have been completed
* @returns Whether the step should be enabled
*/
isEnabled?: (groups: FormGroup<T>[], completedSteps: string[]) => boolean;
/**
* Optional function to determine if the step is completed
* If not provided, the step will be considered completed if it's valid
*
* @param groups - The form groups associated with this step
* @returns Whether the step is completed
*/
isCompleted?: (groups: FormGroup<T>[]) => boolean;
/**
* Optional function to run when entering this step
* Useful for initialization, fetching data, etc.
*
* @param groups - All form groups
*/
onEnter?: (groups: FormGroup<T>[]) => void | Promise<void>;
/**
* Optional function to run when leaving this step
* Useful for cleanup, saving data, etc.
*
* @param groups - All form groups
* @param direction - The direction of navigation ('next' or 'prev')
* @returns Whether navigation should proceed (can be used to prevent leaving the step)
*/
onLeave?: (groups: FormGroup<T>[], direction: 'next' | 'prev') => boolean | Promise<boolean>;
}
/**
* Configuration options for the form wizard
*
* @template T - The type of form data
*/
export interface FormWizardConfig<T> {
/** Array of steps in the wizard */
steps: FormStep<T>[];
/**
* Initial step ID to start with
* If not provided, the first step will be used
*/
initialStepId?: string;
/**
* Whether to validate the current step when navigating to the next step
* Default: true
*/
validateOnNext?: boolean;
/**
* Whether to allow navigation to any step, even if previous steps are not completed
* Default: false
*/
allowSkipSteps?: boolean;
/**
* Whether to mark a step as completed when navigating away from it
* Default: true
*/
markCompletedOnLeave?: boolean;
/**
* Whether to persist the wizard state (current step, completed steps) in storage
* Default: false
*/
persistState?: boolean;
/**
* Storage key to use when persisting wizard state
* Default: 'reform-wizard-state'
*/
persistStateKey?: string;
/**
* Callback fired when a step is completed
*
* @param stepId - The ID of the completed step
* @param groups - All form groups
*/
onStepCompleted?: (stepId: string, groups: FormGroup<T>[]) => void;
/**
* Callback fired when all steps are completed
*
* @param groups - All form groups
*/
onWizardCompleted?: (groups: FormGroup<T>[]) => void;
}
/**
* State of the form wizard
*/
export interface FormWizardState {
/** ID of the current active step */
currentStepId: string;
/** Array of step IDs that have been completed */
completedSteps: string[];
/** Whether the wizard is in the process of validating */
isValidating: boolean;
/** Whether the wizard is transitioning between steps */
isTransitioning: boolean;
/** Whether all steps have been completed */
isCompleted: boolean;
}
/**
* Navigation methods for the form wizard
*/
export interface FormWizardNavigation {
/**
* Navigate to the next step
* Will validate the current step first if validateOnNext is true
*
* @returns Promise that resolves to whether navigation was successful
*/
next: () => Promise<boolean>;
/**
* Navigate to the previous step
*
* @returns Promise that resolves to whether navigation was successful
*/
prev: () => Promise<boolean>;
/**
* Navigate to a specific step by ID
*
* @param stepId - The ID of the step to navigate to
* @returns Promise that resolves to whether navigation was successful
*/
goToStep: (stepId: string) => Promise<boolean>;
/**
* Reset the wizard to its initial state
*
* @param options - Reset options
*/
resetWizard: (options?: {
/** Whether to also reset form data */
resetFormData?: boolean;
/** Whether to clear completed steps */
clearCompletedSteps?: boolean;
}) => void;
}
/**
* Step management methods for the form wizard
*
* @template T - The type of form data
*/
export interface FormWizardStepManager<T> {
/**
* Get all steps in the wizard
*
* @returns Array of steps with additional status information
*/
getSteps: () => Array<Omit<FormStep<T>, 'isEnabled' | 'isCompleted'> & {
/** Whether the step is the current active step */
isActive: boolean;
/** Whether the step has been completed */
isCompleted: boolean;
/** Whether the step is enabled and can be navigated to */
isEnabled: boolean;
/** Original step isEnabled function if it exists */
checkEnabled?: FormStep<T>['isEnabled'];
/** Original step isCompleted function if it exists */
checkCompleted?: FormStep<T>['isCompleted'];
}>;
/**
* Get a specific step by ID
*
* @param stepId - The ID of the step to get
* @returns The step with additional status information, or undefined if not found
*/
getStep: (stepId: string) => (Omit<FormStep<T>, 'isEnabled' | 'isCompleted'> & {
isActive: boolean;
isCompleted: boolean;
isEnabled: boolean;
checkEnabled?: FormStep<T>['isEnabled'];
checkCompleted?: FormStep<T>['isCompleted'];
}) | undefined;
/**
* Get the current active step
*
* @returns The current step with additional status information
*/
getCurrentStep: () => Omit<FormStep<T>, 'isEnabled' | 'isCompleted'> & {
isActive: boolean;
isCompleted: boolean;
isEnabled: boolean;
checkEnabled?: FormStep<T>['isEnabled'];
checkCompleted?: FormStep<T>['isCompleted'];
};
/**
* Mark a step as completed
*
* @param stepId - The ID of the step to mark as completed
*/
markStepCompleted: (stepId: string) => void;
/**
* Mark a step as not completed
*
* @param stepId - The ID of the step to mark as not completed
*/
markStepNotCompleted: (stepId: string) => void;
/**
* Validate a specific step
*
* @param stepId - The ID of the step to validate
* @returns Whether the step is valid
*/
validateStep: (stepId: string) => Promise<boolean>;
}
/**
* Return type of the useFormWizard hook
*
* @template T - The type of form data
*/
export interface FormWizardReturn<T> extends FormWizardState, FormWizardNavigation, FormWizardStepManager<T> {
/** The original wizard configuration */
config: FormWizardConfig<T>;
}