String input constrained by a mask pattern or preset. Ideal for credit cards, expiry dates, ZIP codes, and formatted identifiers.
- First argument is required: a built-in
MASKSpreset, a raw pattern string, or a{ pattern, tokens }object - Label the field separately with
label(...)since the constructor takes the mask, not the label - Your application-owned input chooses its width and input mode, while the controller formats and unmasks the value
Defaults, inheritance & field methods
- First argument is required: a
MASKSpreset, a custom pattern string, or a{ pattern, tokens }object - defaultValue is
'' - Masked values are stored by default (separators like
/,-, spaces are preserved) - Shared methods: see Base field builder
- String builder methods: see field.text()
Mask-specific methods:
| Method | Type | Description |
|---|---|---|
storeRaw() | () => this | Stores the unformatted raw payload instead of the masked value. |
storeMasked() | () => this | Explicitly keeps the formatted masked value, which is the default behavior. |
showPlaceholder(char?) | char?: string | Renders placeholder characters inside the current value. |
showMaskInPlaceholder(charOrText?) | charOrText?: string | Renders the mask as placeholder text while keeping the actual value empty. |
tokens(map) | map: Record<string, RegExp> | Adds or overrides token characters for advanced masks. |
validateComplete(message?) | message?: string | Requires the entire mask to be filled before submit. |
Adaptive mask runtime
FormBridge exposes mask state and operations through form.fieldController(name); your application renders the input.
- Bind the input to
displayValueand forward changes toonChange() - Use
mask.placeholder/mask.placeholderTextto describe the expected shape rawValue,maskComplete,format(), andunmask()are available for custom feedback- Choose
inputMode, keyboard type, width, and visual treatment in your own component
The examples above define a reusable application-owned MaskedField; no UI component is imported from FormBridge.
Recipes
Patterns that showcase mask-specific strengths.
Credit card with placeholder
CardNumber.tsxtsx
| 1 | import { MASKS } from '@runilib/react-formbridge' |
| 2 | |
| 3 | const schema = { |
| 4 | cardNumber: field.masked(MASKS.CARD_16) |
| 5 | .label('Card number') |
| 6 | .required() |
| 7 | .showMaskInPlaceholder() |
| 8 | .validateComplete('Card number is incomplete.'), |
| 9 | } |
Expiry + CVV side by side
ExpiryCvv.tsxtsx
| 1 | import { MASKS } from '@runilib/react-formbridge' |
| 2 | |
| 3 | const schema = { |
| 4 | expiry: field.masked(MASKS.EXPIRY).label('Expiry').required(), |
| 5 | cvv: field.masked(MASKS.CVV).label('CVV').required(), |
| 6 | } |
Raw backup code (strip separators)
BackupCode.tsxtsx
| 1 | const schema = { |
| 2 | backupCode: field.masked('9999-9999') |
| 3 | .label('Backup code') |
| 4 | .storeRaw() |
| 5 | .validateComplete(), |
| 6 | } |
Custom plate with uppercase token
LicensePlate.tsxtsx
| 1 | const schema = { |
| 2 | plate: field.masked('LL-999-LL') |
| 3 | .label('Plate') |
| 4 | .tokens({ L: /[A-Z]/ }) |
| 5 | .uppercase(), |
| 6 | } |
French IBAN
IbanFr.tsxtsx
| 1 | import { MASKS } from '@runilib/react-formbridge' |
| 2 | |
| 3 | const schema = { |
| 4 | iban: field.masked(MASKS.IBAN_FR) |
| 5 | .label('IBAN') |
| 6 | .required() |
| 7 | .validateComplete('IBAN is incomplete.'), |
| 8 | } |
Pattern syntax
9= digita= letter*= any character- Any other character is treated as a visible separator
- Use
tokens({...})to add custom mask characters such asLfor uppercase-only letters
Built-in MASKS presets
Pass any of these presets as field.masked(MASKS.X).label('Label').
Cards
CARD_169999 9999 9999 9999
CARD_AMEX9999 999999 99999
CARD_199999 9999 9999 9999 999
Security / expiry
CVV999
CVV_AMEX9999
EXPIRY99/99
Date / time
DATE_DMY99/99/9999
DATE_MDY99/99/9999
DATE_ISO9999-99-99
TIME_HM99:99
TIME_HMS99:99:99
DATETIME99/99/9999 99:99
Bank / finance
IBAN_FRaa99 9999 9999 9999 9999 9999 999
IBAN_DEaa99 9999 9999 9999 9999 99
IBAN_GBaa99 aaaa 9999 9999 9999 99
IBANaa99 9999 9999 9999 9999 9999 9999 99
BANK_NZ99-9999-9999999-99
SIREN999 999 999
SIRET999 999 999 99999
Postal / identity
ZIP_FR99999
ZIP_US99999
ZIP_US_PLUS499999-9999
POSTCODE_UKaa9 9aa
SSN999-99-9999
NIR_FR9 99 99 99 999 999 99
Other
IP_ADDRESS999.999.999.999
DURATION99:99:99.999
NUMBER_FR9 999 999