Most builders share the same fluent inheritance tree, so the quickest way to read the API is to start with the common base surface and then add the builder-specific methods.
Inherited from BaseFieldBuilder:
| Method | Type | Description |
|---|---|---|
defaultValue | (value) => this | Overrides the default value set in the constructor. |
required | (message?) => this | Marks the field as required. A validation error is shown if the field is left empty. |
optional | () => this | Marks the field as optional (removes the required constraint). Useful when extending a schema where the field was previously required. |
label | (text) => this | Overrides the label set in the constructor. |
placeholder | (text?) => this | Sets the placeholder text displayed inside the field when it is empty. |
hint | (text) => this | Adds a helper/hint text displayed below the field to guide the user. |
disabled | (value = true) => this | Disables (or re-enables) the field. A disabled field is rendered but not interactive. |
hidden | (value = true) => this | Hides (or shows) the field. A hidden field is not rendered at all. |
debounce | (ms) => this | Sets the debounce delay (in milliseconds) for value changes. Validation and side-effects are deferred until the user stops typing for the specified duration. |
validate | (fn) => this | Adds a custom validation function to the field. Multiple validators can be chained - they run in order and the first error message returned is displayed. |
validateAsync | (fn) => this | Alias for validate() when the intent is explicitly asynchronous. Useful for username availability checks, server-side uniqueness validation, promo code verification, and other async rules. |
transform | (fn) => this | Registers a transform function that is applied to the field value before validation and submission (e.g. trimming whitespace, normalizing case). |
render | (fn) => this | Provides a custom render function to completely override the default field rendering. Use this when the built-in field components don't meet your UI needs. |
Conditional logic helpers:
| Method | Type | Description |
|---|---|---|
visibleWhen | (fieldOrFn, value?) => this | Makes the field conditionally visible based on another field's value or a custom predicate function. Multiple visibleWhen* calls are combined with AND logic. |
visibleAndRequiredWhen | (fieldOrFn, value?) => this | Makes the field both visible and required when the condition is met. Shorthand for calling visibleWhen() and requiredWhen() with the same condition. |
visibleWhenNot | (field, value) => this | Makes the field visible when the referenced field does not equal the given value. |
visibleWhenTruthy | (field) => this | Makes the field visible when the referenced field has a truthy value (any value that is not false, 0, '', null, or undefined). |
visibleWhenFalsy | (field) => this | Makes the field visible when the referenced field has a falsy value (false, 0, '', null, or undefined). |
visibleWhenAny | (pairs) => this | Makes the field visible when any of the given field/value pairs match (OR logic). |
requiredWhen | (fieldOrFn, value?) => this | Makes the field conditionally required based on another field's value or a custom predicate function. |
requiredWhenAny | (pairs) => this | Makes the field required when any of the given field/value pairs match (OR logic). |
disabledWhen | (fieldOrFn, value?) => this | Conditionally disables the field based on another field's value or a custom predicate function. |
resetOnHide | () => this | When the field becomes hidden (via a visibleWhen* condition), resets its value back to the default value. |
keepOnHide | () => this | When the field becomes hidden, keeps its current value intact. The value is preserved and will be included in form submission. |
clearOnHide | () => this | When the field becomes hidden, clears its value entirely (sets it to an empty/null state). |
Inherited from StringFieldBuilder:
| Method | Type | Description |
|---|---|---|
min | (length, message?) => this | Minimum string length. |
max | (length, message?) => this | Maximum string length. |
pattern | (regex | regex[], message?) => this | Regex pattern or accepted regex alternatives. |
patterns | (regexes, message?) => this | Alias for pattern() when passing multiple accepted regex alternatives. |
format | (regex, message?) => this | Internal base format pattern used by built-in field presets like email/url/tel. |
trim | () => this | Trim value before validation / submit. |
lowercase | () => this | Lowercase the value on every keystroke. |
uppercase | () => this | Uppercase the value on every keystroke. |
nonEmpty | (message?) => this | Rejects empty and whitespace-only strings (stricter than required()). |
length | (exact, message?) => this | Requires an exact character count for fixed-size codes. |
between | (min, max, message?) => this | Shorthand for a combined min+max length check. |
oneOf | (values, message?) => this | Restricts accepted values to an allow-list. |
notOneOf | (values, message?) => this | Blocks values from a deny-list (reserved words, forbidden slugs, etc.). |
matches | (fieldName, message?) => this | Must match the value of another field (e.g. confirm password). Supports ref() paths. |
sameAs | (fieldName, message?) => this | Alias for matches() with more explicit semantics. |
Special cases:
| Builder | Extends base with | Notes |
|---|---|---|
field.select() / field.radio() | options(...), optionsFrom(...), searchable(...) | Picker-style builders |
field.phone() | defaultCountry(), storeE164(), country-aware phone helpers | Extends base directly |
field.file() | Upload-focused surface | Main exception - does not expose render(), transform(), or the conditional helpers from BaseFieldBuilder |
Behavior vs UI
Builders describe form semantics: defaults, validation, normalization, labels, hints, conditions, and type-specific metadata. They do not style or generate inputs.
Read that metadata from fieldController(name) and pass it to your application components. Reusable visual rules belong in your design-system adapters; reusable form behavior belongs in the schema.
Shared method examples
Mini examples for the shared base builder methods:
defaultValue('FR')field.select('Country').defaultValue('FR')required('Required') / optional()field.text('Middle name').required('Required').optional()label('Username') / placeholder('@alex') / hint('Shown publicly')field.text('Handle').label('Username').placeholder('@alex').hint('Shown publicly')disabled() / hidden() / debounce(500)field.text('Referral code').disabled().hidden(false).debounce(500)validate((value) => value ? null : 'Missing')field.text('Company').validate((value) => value.length >= 2 ? null : 'Use at least 2 characters')transform((value) => value.trim())field.text('Slug').transform((value) => value.trim().toLowerCase().replace(/\s+/g, '-'))render(fn)field.custom(0).label('Rating').render(({ value, onChange }) => <Stars value={value} onChange={onChange} />)visibleWhen('accountType', 'company')field.text('Company name').visibleWhen('accountType', 'company')visibleAndRequiredWhen('accountType', 'company')field.text('Company name').visibleAndRequiredWhen('accountType', 'company')visibleWhenNot('role', 'guest') / visibleWhenTruthy('hasVat') / visibleWhenFalsy('sameAsBilling')field.text('VAT number').visibleWhenTruthy('hasVat')visibleWhenAny([['role', 'admin'], ['role', 'manager']])field.text('Internal note').visibleWhenAny([['role', 'admin'], ['role', 'manager']])requiredWhen('needsInvoice') / requiredWhenAny([['country', 'FR'], ['country', 'DE']])field.text('Tax ID').requiredWhenAny([['country', 'FR'], ['country', 'DE']])disabledWhen('submitted')field.text('Coupon code').disabledWhen('submitted')resetOnHide() / keepOnHide() / clearOnHide()field.text('Other').visibleWhen('reason', 'other').resetOnHide()_build()const descriptor = field.text('Debug').required()._build()Mini examples for the shared string builder methods:
min(3) / max(20)field.text('Username').trim().min(3).max(20)pattern(/^[A-Z]{3}-\d{4}$/)field.text('Partner code').pattern(/^[A-Z]{3}-\d{4}$/)patterns([/^FR-/, /^DE-/], 'Use an EU code')field.text('Region code').patterns([/^FR-/, /^DE-/], 'Use an EU code')format(/^https:\/\/.+$/, 'Use HTTPS')field.url('Webhook URL').format(/^https:\/\/.+$/, 'Use HTTPS')trim() / lowercase() / uppercase()field.email('Email').trim().lowercase()` and `field.masked('LL-999-LL').label('Plate').uppercase()matches('password') / sameAs('password')field.password('Confirm password').sameAs('password', 'Passwords must match')