Types Reference
All types are exported from @saastro/forms. This page documents every type file and its key exports. Types that have dedicated guide pages link to them for detailed usage.
types/common.ts
Core form configuration types.
FormConfig
The top-level configuration object returned by FormBuilder.build().
interface FormConfig {
formId: string;
fields: Record<string, FieldConfig>;
steps: Record<string, Step>;
initialStep?: string;
layout?: FormLayout;
buttons?: FormButtons;
submitConfirmation?: SubmitConfirmationConfig;
pluginManager?: PluginManager;
successMessage?: string | ((values: Record<string, unknown>) => string);
errorMessage?: string | ((error: Error, values: Record<string, unknown>) => string);
redirect?: string | ((values: Record<string, unknown>) => string);
submitActions?: Record<string, SubmitActionNode>;
submitExecution?: SubmitExecutionConfig;
onStepChange?: (step: string) => void;
onSuccess?: (values: Record<string, unknown>) => void;
onError?: (error: Error, values: Record<string, unknown>) => void;
}
See: FormBuilder API
FormLayout
Controls the form grid system.
interface FormLayout {
mode: 'auto' | 'manual';
gap?: GapValue; // 0-12
minFieldWidth?: number; // Pixels, auto mode only (default: 240)
columns?: ColumnsValue; // 1-12
className?: string; // Extra CSS classes for grid container
}
See: Layout System
Breakpoint
type Breakpoint = 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
SubmitConfirmationConfig
Double-click confirmation for forms with optional fields.
interface SubmitConfirmationConfig {
optionalFields: Array<{ name: string; message: string }>;
buttonBehavior: {
defaultText?: string;
warningText: string;
warningVariant?: ButtonConfig['variant'];
warningEffect?: ButtonConfig['effect'];
resetDelay?: number; // ms, default: 3000
};
applyOn: 'submit' | 'steps' | 'both';
showOnce?: boolean; // default: true
}
See: FormBuilder API
types/fields.ts
The discriminated union of all 21+ field types.
FieldConfig
type FieldConfig =
| TextFieldProps // type: 'text' | 'email' | 'tel'
| TextareaFieldProps // type: 'textarea'
| SliderFieldProps // type: 'slider'
| SelectFieldProps // type: 'select'
| ComboboxFieldProps // type: 'combobox'
| NativeSelectFieldProps // type: 'native-select'
| RadioFieldProps // type: 'radio'
| ButtonRadioFieldProps // type: 'button-radio'
| CheckboxFieldProps // type: 'checkbox'
| SwitchFieldProps // type: 'switch'
| CheckboxGroupFieldProps // type: 'checkbox-group'
| SwitchGroupFieldProps // type: 'switch-group'
| ButtonCheckboxFieldProps // type: 'button-checkbox'
| DateFieldProps // type: 'date'
| DateRangeFieldProps // type: 'daterange'
| HtmlFieldProps // type: 'html'
| ButtonCardFieldProps // type: 'button-card'
| OtpFieldProps // type: 'otp'
| CommandFieldProps // type: 'command'
| InputGroupFieldProps // type: 'input-group'
| ButtonConfig; // type: 'button' | 'submit' | 'next' | 'back'
BaseFieldProps
All field types extend this base:
interface BaseFieldProps
extends
LabelProps,
LayoutProps,
InputProps,
ValidationProps,
StateProps,
TransformProps,
AdvancedProps {}
Key properties inherited by all fields:
| Category | Properties |
|---|---|
| Label | label, hideLabel, label_className, description |
| Layout | layout, columns, gridSpan, order, wrapper_className, className |
| Input | input_className, value, defaultValue, placeholder, autocomplete, required, size, icon, iconProps |
| Validation | schema, customValidators, error_className, helperText, helper_className, tooltip |
| State | hidden, disabled, readOnly |
| Transform | transform |
| Advanced | trackingKey |
FieldLayoutConfig
interface FieldLayoutConfig {
columns?: Partial<Record<Breakpoint, number>>; // 1-12 per breakpoint
order?: number | Partial<Record<Breakpoint, number>>;
}
Option
Used by select, radio, combobox, command, button-radio, checkbox-group, switch-group, button-checkbox:
type Option = {
label: string;
value: string;
icon?: ReactNode;
iconProps?: Record<string, unknown>;
};
ButtonCardOption
Used by button-card:
type ButtonCardOption = {
value: string;
text: string;
description?: string;
icon?: ReactNode;
iconProps?: Record<string, unknown>;
};
types/buttons.ts
ButtonConfig
interface ButtonConfig extends BaseFieldProps {
type: 'button' | 'submit' | 'next' | 'back';
action?: () => void;
loading?: boolean;
icon?: ReactNode;
iconPosition?: 'left' | 'right';
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
effect?:
| 'default'
| 'expandIcon'
| 'ringHover'
| 'shine'
| 'shineHover'
| 'gooeyRight'
| 'gooeyLeft'
| 'underline'
| 'hoverUnderline';
rounded?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
label?: string;
}
FormButtons
interface FormButtons {
submit?: ButtonConfig;
next?: ButtonConfig;
back?: ButtonConfig;
align?: 'start' | 'center' | 'end' | 'between' | 'responsive';
inline?: boolean;
}
See: Buttons
types/steps.ts
Step
type Step = {
id?: string; // Optional — key serves as id in Record<string, Step>
fields: string[]; // Field names in this step
next?: StepCondition[];
defaultNext?: string; // Fallback if no condition matches
};
StepCondition
type StepCondition = ConditionGroup & {
target: string; // Step id to navigate to
};
See: Multi-Step Forms
types/logic.ts
ConditionOperator
type ConditionOperator =
| 'equals'
| 'notEquals'
| 'contains'
| 'notContains'
| 'greaterThan'
| 'lessThan'
| 'greaterThanOrEqual'
| 'lessThanOrEqual'
| 'isTrue'
| 'isFalse'
| 'isEmpty'
| 'isNotEmpty';
Condition
type Condition = {
field: string;
operator: ConditionOperator;
value?: string | number | boolean | null;
};
ConditionGroup
type ConditionGroup = {
conditions: Condition[];
operator: 'AND' | 'OR';
};
See: Conditional Logic, Multi-Step Forms
types/submitActions.ts
SubmitActionNode
The complete configuration for a single submit action:
interface SubmitActionNode {
id: string;
action: SubmitAction;
trigger: SubmitTrigger;
condition?: SubmitActionCondition;
order?: number;
continueOnError?: boolean;
disabled?: boolean;
fieldMapping?: FieldMappingConfig;
}
SubmitAction (union)
type SubmitAction =
| HttpSubmitAction // type: 'http'
| WebhookSubmitAction // type: 'webhook'
| EmailSubmitAction // type: 'email'
| CustomSubmitAction; // type: 'custom'
SubmitTrigger
type SubmitTriggerType =
| 'onSubmit'
| 'onStepEnter'
| 'onStepExit'
| 'onFieldChange'
| 'onFieldBlur'
| 'onDelay'
| 'manual';
interface SubmitTrigger {
type: SubmitTriggerType;
stepId?: string;
fieldName?: string;
delayMs?: number;
debounceMs?: number;
}
FieldMapping
interface FieldMapping {
fields?: Record<string, string | FieldMapEntry>;
inject?: Record<string, unknown>;
exclude?: string[];
passthrough?: boolean; // default: true
}
interface FieldMapEntry {
to: string;
transform?: BuiltinTransform | FieldTransformFn;
}
type BuiltinTransform =
| 'toString'
| 'toNumber'
| 'toBoolean'
| 'booleanString'
| 'dateISO'
| 'dateYMD'
| 'dateDMY'
| 'dateTimestamp'
| 'trim'
| 'lowercase'
| 'uppercase'
| 'emptyToNull';
FieldResolver
type FieldResolver =
| { $resolver: 'timestamp' }
| { $resolver: 'hostname' }
| { $resolver: 'urlParam'; param: string; fallback?: string }
| { $resolver: 'custom'; fn: () => unknown };
SubmitExecutionConfig
interface SubmitExecutionConfig {
mode: 'sequential' | 'parallel';
stopOnFirstError?: boolean;
globalTimeout?: number;
}
SubmitActionsResult
interface SubmitActionsResult {
results: SubmitActionResult[];
allSuccessful: boolean;
successCount: number;
failureCount: number;
totalDurationMs: number;
}
interface SubmitActionResult {
actionId: string;
actionName: string;
success: boolean;
data?: unknown;
error?: Error;
durationMs: number;
startedAt: Date;
completedAt: Date;
}
See: Submit & Actions
types/plugin.ts
FormPlugin
interface FormPlugin {
name: string;
version: string;
description?: string;
options?: Record<string, unknown>;
init?: (options?) => void;
cleanup?: () => void;
onFormInit?: (config: FormConfig) => void;
onFieldChange?: (fieldName: string, value: unknown, allValues: Record<string, unknown>) => void;
onStepChange?: (stepId: string, values: Record<string, unknown>) => void;
onBeforeSubmit?: (values: Record<string, unknown>) => void | Promise<void>;
onAfterSubmit?: (values: Record<string, unknown>, response: unknown) => void;
onError?: (error: Error, values?: Record<string, unknown>) => void;
transformConfig?: (config: FormConfig) => FormConfig;
transformValues?: (
values: Record<string, unknown>,
) => Record<string, unknown> | Promise<Record<string, unknown>>;
registerFields?: () => Record<string, FieldRenderer>;
validators?: Record<
string,
(value: unknown, context: ValidationContext) => boolean | string | Promise<boolean | string>
>;
}
ValidationContext
interface ValidationContext {
fieldName: string;
allValues: Record<string, unknown>;
abortSignal?: AbortSignal;
}
FieldRenderer
type FieldRenderer = React.ComponentType<{
name: string;
fieldConfig: any;
control: any;
colSpanItem: string;
}>;
definePlugin()
function definePlugin(plugin: FormPlugin): FormPlugin;
See: Plugins
types/validation.ts
ValidationRules
Serializable validation rules compiled to Zod at runtime:
type ValidationRules = {
required?: boolean;
requiredMessage?: string;
minLength?: number;
minLengthMessage?: string;
maxLength?: number;
maxLengthMessage?: string;
pattern?: string;
patternMessage?: string;
format?: 'email' | 'url' | 'uuid' | 'cuid' | 'emoji';
formatMessage?: string;
min?: number;
minMessage?: string;
max?: number;
maxMessage?: string;
integer?: boolean;
integerMessage?: string;
positive?: boolean;
positiveMessage?: string;
minItems?: number;
minItemsMessage?: string;
maxItems?: number;
maxItemsMessage?: string;
mustBeTrue?: boolean;
mustBeTrueMessage?: string;
minDate?: string;
minDateMessage?: string;
maxDate?: string;
maxDateMessage?: string;
mustBeFuture?: boolean;
mustBeFutureMessage?: string;
mustBePast?: boolean;
mustBePastMessage?: string;
preset?: string;
};
SchemaType
type SchemaType = z.ZodType | ValidationRules;
See: Validation
types/components.ts
ComponentRegistry
The full 49-slot interface for UI component injection. See Component System for the complete table.
interface ComponentRegistry {
// Inputs (4): Input, Textarea, Button, Label
// Checkbox & Switch (2): Checkbox, Switch
// Radio (2): RadioGroup, RadioGroupItem
// Select (5): Select, SelectTrigger, SelectContent, SelectItem, SelectValue
// Native Select (1): NativeSelect
// Slider (1): Slider
// Popover (3): Popover, PopoverTrigger, PopoverContent
// Tooltip (4): Tooltip, TooltipTrigger, TooltipContent, TooltipProvider
// Separator (1): Separator
// Dialog (6): Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription
// Command (6): Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem
// Input OTP (3): InputOTP, InputOTPGroup, InputOTPSlot
// Accordion (4): Accordion, AccordionItem, AccordionTrigger, AccordionContent
// Calendar (1): Calendar
// Form (2): FormField, FormControl
// Field (4): Field, FieldLabel, FieldDescription, FieldError
}
Helper Types
type PartialComponentRegistry = Partial<ComponentRegistry>;
type ComponentRegistryInput = { [K in keyof ComponentRegistry]: React.ComponentType<any> };
type ComponentOverrides = Partial<{ [K in keyof ComponentRegistry]: React.ComponentType<any> }>;
See: Component System