import { RegisteredRouter } from "@tanstack/react-router"; import { RoutePaths } from "@tanstack/router-core"; import { CommonProps, Refable, type Styleable } from "@trackunit/react-components"; import { MappedOmit } from "@trackunit/shared-utils"; import { ReactNode } from "react"; import { UseFormReturn } from "react-hook-form"; import { AnyZodObject, SomeZodObject, z } from "zod"; export type StepState = "active" | "done" | "invalid" | "disabled" | "ready"; export type StepDefinitions = { [KeyFullStep in keyof z.TypeOf]: KeyFullStep extends `${infer KeyParentStep}/${infer _KeySubStep}` ? KeyParentStep extends keyof z.TypeOf ? DefinedStep[KeyFullStep], z.TypeOf> & { shouldRender?: (fullFormState: Partial>) => boolean; } : never : DefinedStep[KeyFullStep], z.TypeOf>; }; export type StepComponentPropsInner> = { form: UseFormReturn; fullForm: UseFormReturn; setSubmitHandler: ((onFinalSubmit: (fullFormState: TFullSchemaValue) => void) => void) | null; beforeStepSubmit?: ((beforeSubmit: (fullFormState: TFullSchemaValue) => void) => void) | null; resetFullFormState?: ((reset: () => void) => void) | null; /** Lets the step disable the footer's primary action, e.g. after a completed final submit. */ setPrimaryActionDisabled?: ((disabled: boolean) => void) | null; }; export interface SimpleStepProps { title: string; description: string | ReactNode; sidebarDescription?: string; containerClassName?: string; } interface DefinedStep> extends SimpleStepProps { component: (props: StepComponentPropsInner) => ReactNode; onPrimaryAction?: (form: UseFormReturn) => Promise | void; defaultValues?: Partial; } export type StepComponentProps AnyZodObject, TStepKey extends keyof z.TypeOf>> = StepComponentPropsInner>[TStepKey], z.TypeOf>>; export interface FromWizardComponentProps> extends MappedOmit, "steps">, CommonProps, Refable, Styleable { steps: TComponentStepDefinitions; } type StepPathString = `${string}/$stepPath`; export type StringWithStepKey = [TPath] extends [never] ? StepPathString : string extends TPath ? StepPathString : TPath extends StepPathString ? TPath : never; /** * The main props interface for the useFormWizard hook. * This interface contains the full configuration needed * for the Hook to generate the props for the wizard component. */ export interface UseFormWizardProps> { fullFormSchema: TFullSchema; lastStepPrimaryActionLabel: string; onCancel?: (stepKey: string) => void; basePath: StringWithStepKey<`${RoutePaths}`>; steps: TStepDefinitions; isEdit?: boolean; } /** * Generates the props for rendering a Form Wizard component. * This hook processes the provided step definitions and form schema to prepare the necessary props for the Form Wizard component. * * @param props Configuration options for the Form Wizard component. * @param props.fullFormSchema The Zod schema for the entire form. * @param props.lastStepPrimaryActionLabel Label for the primary action button on the last step. * @param props.onCancel Callback to execute when canceling the form submission. Defaults to navigating to the parent route. * @param props.basePath Base path for routing within the form wizard. * @param props.steps Definitions for each step in the form wizard. Keys are used as path and a slash is used to define a substep. * @param props.isEdit Indicates whether the form is being edited or created. If the step has a default value, it is considered valid when editing. * @example * ``` * typescript * import { useFormWizard } from './path/to/useFormWizard'; * const { steps,...wizardProps } = useFormWizard({ * fullFormSchema: useYourZodSchema(), * lastStepPrimaryActionLabel: 'Finish', * basePath: '/your-base-path/$stepPath', * steps: { * entry: { * title: "Add your thing", * description: Choose how to add your thing, * sidebarDescription: Choose how to add your thing, * defaultValues: { entryMethod: "upload" }, * component: stepProps => , * }, * "entry/manual": { * shouldRender: fullFormState => fullFormState.entry?.entryMethod === "manual", * title: "Type your thing", * description: "Manually type your thing", * component: stepProps => , * }, * "entry/upload": { * shouldRender: fullFormState => fullFormState.entry?.entryMethod === "upload", * title: "Upload your thing", * description: "Upload a spreadsheet thing", * component: stepProps => , * }, * review: { * title: "Review & Save", * description: "Make sure everything looks alright", * sidebarDescription: "Make sure everything looks alright", * component: stepProps => , * }, * }, * ``` }); */ export declare const useFormWizard: , TFullSchema extends AnyZodObject>(props: UseFormWizardProps) => FromWizardComponentProps>; export {};