import { ClientTaxDocumentation } from '@taxbit/utilities'; import { ExternalValidations } from 'types/client'; import { DateFormatOrder, HydratedElement, HydratedInput, StateDeriver } from 'types/FieldDescriptor'; import { ControllingPersonToggle } from 'types/HydratedControllingPerson'; import { InputStep } from 'types/InputStep'; import { Locale } from 'types/Locale'; import { AdaptiveMode } from 'types/props'; import { QuestionnaireProp } from 'types/QuestionnaireProp'; import { QuestionnaireState } from 'types/QuestionnaireState'; import { UiState } from 'types/UiState'; import { UsTinValidationAttempt } from '../hooks/useUsTinValidation/useUsTinValidation'; import { Index } from './fields/residencyFields'; export type DescriptorConfig = { questionnaire: QuestionnaireProp; treatyClaims: boolean; realTimeTinValidation: boolean; dateFormat: DateFormatOrder; minimumAge: number; adaptiveMode?: AdaptiveMode; poweredByTaxbit?: boolean; /** Raw client-provided data, pre-transform. Used to distinguish '' from undefined. */ data?: ClientTaxDocumentation; }; export type ServerState = { externalValidations?: ExternalValidations; usTinValidations: UsTinValidationAttempt[]; }; export type DescriptorState = { fields: QuestionnaireState; ui: UiState; config: DescriptorConfig; server: ServerState; }; export type FlowDescriptor = { questionnaire: QuestionnaireProp; /** * Human-readable name describing the flow + active config variants * (e.g., "W-FORM Treaty Claims + Real-Time TIN Validation"). */ name: string; /** * Ordered, exhaustive list of steps that *could* appear in this flow. * Runtime visibility within the flow is decided by each step's getVisible. */ steps: InputStep[]; }; /** * Verification a step requests when the user clicks Next. The descriptor * carries the actual values to verify; the hook routes by `type` to the * appropriate runtime function (e.g., `doValidateUsTin`). */ export type StepVerification = { type: 'us-tin'; name: string; tin: string; }; export type StepDescriptor = { key: string; getTitle: StateDeriver; getSubTitle?: StateDeriver; /** Static item list, or a function that returns items based on state (e.g., for adaptive :display). */ items: string[] | StateDeriver; /** Called once when the step is first hydrated. Use for side effects like showing errors on entry. */ onLoad?: (state: DescriptorState) => void; /** * Whether this step appears in the flow given the current state. Combines * runtime gating (DRE branching, derived data, adaptive-skip coverage) * into one predicate. Defaults to `() => true` when not declared. */ getVisible?: StateDeriver; /** * Whether the primary action on this step is a "next" (verify + advance) or * a "submit" (invoke onSubmit prop). Defaults to `'next'` when not declared. */ getActionType?: StateDeriver<'next' | 'submit'>; /** * Verifications to run when the user clicks Next on this step. Each entry * is a data declaration, not a callback — the hook routes by `type` to the * appropriate runtime function (e.g., `doValidateUsTin`). Empty/undefined * means no extra verification beyond the standard error check. */ getVerifications?: StateDeriver; }; export type HydratedSection = { type: 'section'; title?: string; subTitle?: string; required?: boolean; items: HydratedItem[]; }; export type HydratedControllingPerson = { type: 'controllingPerson'; title: string; items: HydratedItem[]; remove?: ControllingPersonToggle; add?: ControllingPersonToggle; }; export type HydratedResidence = { index: Index; title: string; items: HydratedItem[]; remove?: ControllingPersonToggle; add?: ControllingPersonToggle; }; export type HydratedResidencies = { type: 'residencies'; key: string; errorMessages?: string[]; errorMessageId?: string; residences: HydratedResidence[]; confirmation?: HydratedInput; }; export type HydratedItem = HydratedElement | HydratedSection | HydratedControllingPerson | HydratedResidencies; export type HydratedStateLabels = { formActions: string; formHasErrors: string; }; export type HydratedAction = { onClick: () => void; label: string; disabled: boolean; }; export type HydratedBack = { onClick: () => void; label: string; }; export type HydratedState = { key: string; title: string; subTitle?: string; items: HydratedItem[]; questionnaire?: QuestionnaireProp; language: Locale; poweredByTaxbit?: boolean; labels?: HydratedStateLabels; setLanguage: (locale: Locale) => void; action: HydratedAction; back?: HydratedBack; isVerifying?: boolean; errorMessage?: string; infoMessage?: string; };