Input Mask
Structured text input with token validation, formatting, and completion callbacks.
InputMask guides users through structured values such as phone numbers, dates, card numbers, account codes, and serial numbers while preserving a normal accessible text input.
Basic usage
The mask uses tokens for editable positions and literal characters for separators.
import { InputMask } from '@mosmox/ui';
<InputMask label="Phone number" mask="+1 (999) 999-9999" inputMode="tel" />
<InputMask label="Date" mask="99/99/9999" inputMode="numeric" />Preset masks
Use preset when the format is common. Presets provide the mask, recommended mobile keyboard, and a useful placeholder.
<InputMask label="Phone" preset="phone" />
<InputMask label="International phone" preset="internationalPhone" />
<InputMask label="Date" preset="date" />
<InputMask label="Credit card" preset="creditCard" />
<InputMask label="Expiration" preset="expiry" />
<InputMask label="IBAN" preset="iban" />Available presets are listed below. They set the mask, input mode, and placeholder; you can still override these values with explicit props.
| Preset | Mask | Input mode | Example / placeholder |
|---|---|---|---|
phone | (999) 999-9999 | tel | (555) 123-4567 |
internationalPhone | +99 999 999 9999 | tel | +38 067 123 4567 |
date | 99/99/9999 | numeric | DD/MM/YYYY |
time | 99:99 | numeric | HH:MM |
dateTime | 99/99/9999 99:99 | numeric | DD/MM/YYYY HH:MM |
creditCard | 9999 9999 9999 9999 | numeric | 0000 0000 0000 0000 |
expiry | 99/99 | numeric | MM/YY |
cvv | 999 | numeric | CVV |
postalCode | AA9 9AA | text | SW1A 1AA |
zipCode | 99999-9999 | numeric | 12345-6789 |
iban | AA99 9999 9999 9999 9999 9999 | text | UA00 0000 0000 0000 0000 0000 |
sortCode | 99-99-99 | numeric | 20-00-00 |
routingNumber | 999999999 | numeric | 021000021 |
otp | 999999 | numeric | 000000 |
hexColor | HAAAAAA | text | #FFFFFF (H accepts #) |
ipv4 | 999.999.999.999 | numeric | 192.168.001.001 |
slug | ******************** | text | my-project-slug |
licensePlate | AA-9999-AA | text | AA-1234-AA |
Import inputMaskPresets when you need to inspect or reuse the definitions in your own form controls. A custom preset object supports mask, inputMode, placeholder, guide, maskPlaceholder, and formatChars; explicit component props take precedence over the corresponding preset values.
Built-in tokens are:
9— a digit;A— a letter;*— an alphanumeric character;#— a hexadecimal character.
The * token accepts letters and digits, while # accepts hexadecimal characters (0-9, a-f, A-F). Token matching is case-sensitive according to the supplied regular expression.
Literal characters such as +, spaces, parentheses, slashes, and dashes are inserted automatically.
Controlled values and raw values
Use value and onChange for controlled forms. The callback receives both the formatted value and the raw token value.
const [phone, setPhone] = useState('');
<InputMask
mask="+1 (999) 999-9999"
value={phone}
onChange={(formatted, raw) => {
setPhone(formatted);
console.log(raw); // only the digits
}}
/>Use defaultValue for uncontrolled input. onComplete fires once all token positions are valid.
Guide and placeholder modes
Set showMask or guide to display placeholders for unfilled positions. maskPlaceholder customizes the placeholder character.
<InputMask mask="9999 9999" showMask maskPlaceholder="_" />
<InputMask mask="AA-9999" guide maskPlaceholder="•" />Without guide mode, the field stays compact and only renders the part already entered.
Custom tokens
formatChars extends or replaces token definitions for domain-specific formats.
<InputMask
label="Serial number"
mask="SS-999-XX"
formatChars={{
S: /[A-Z]/,
X: /[0-9A-F]/,
}}
/>Custom token keys are any single-character mask symbols not used as literals.
Validation, errors, and states
required reports a required error after blur when no token value exists. Pass error for application validation. onValidityChange reports whether all mask positions are complete.
<InputMask
label="Expiration"
mask="99/99"
required
onValidityChange={(valid) => setValid(valid)}
error={serverError}
helperText="MM/YY"
/>disabled prevents editing. readOnly keeps the formatted value visible without allowing changes. clearable adds a clear action.
The component preserves the caret while inserting, selecting, pasting, and deleting masked characters. Backspace and Delete remove token values without trapping the cursor on literal separators.
Sizes and browser integration
size accepts xs (extra small), sm (small), and default; variant accepts outline and filled. The component follows the same control tokens and slot model as Input, including leadingIcon, prefix, suffix, trailingIcon, loading, clearable, fullWidth, and description. Forward name, id, autoComplete, and inputMode for form integration and mobile keyboard selection. To make a trailing icon actionable, provide onTrailingIconClick and an accessible trailingIconLabel.
<InputMask
name="postalCode"
autoComplete="postal-code"
inputMode="numeric"
size="xs"
mask="99999"
/><InputMask
label="Phone"
preset="phone"
trailingIcon={<span aria-hidden="true">✓</span>}
trailingIconLabel="Verify phone"
onTrailingIconClick={() => alert('Phone verified')}
/>Use a custom preset object when a reusable format needs a local definition:
const employeeCode = {
mask: 'AA-999-XX',
inputMode: 'text' as const,
placeholder: 'AB-123-FF',
};
<InputMask label="Employee code" preset={employeeCode} />Accessibility
The component renders a native text input, associates label with the input, exposes aria-invalid for errors, and supports normal browser editing, selection, paste, and keyboard behavior. Provide aria-label when no visible label is present.
API
| Prop | Type | Default | Description |
|---|---|---|---|
mask | string | — | Mask pattern with token and literal characters. |
preset | InputMaskPresetName | InputMaskPreset | — | Built-in or custom reusable mask definition. preset.mask overrides mask. |
value | string | — | Controlled formatted value. |
defaultValue | string | '' | Initial uncontrolled value. |
onChange | (value, rawValue) => void | — | Called with formatted and raw values. |
onComplete | (value, rawValue) => void | — | Called when every token is filled. |
onValidityChange | (valid) => void | — | Called after input validity changes. |
formatChars | Record<string, RegExp> | built-ins | Custom token definitions. |
maskPlaceholder | string | _ | Character used by guide mode. |
showMask | boolean | false | Displays the mask placeholders. |
guide | boolean | false | Keeps placeholders visible while typing. |
label | ReactNode | — | Visible field label. |
description | ReactNode | — | Supporting text associated with the input. |
placeholder | string | mask | Native placeholder override. |
helperText | ReactNode | — | Supporting text. |
error | ReactNode | — | Validation error content. |
required | boolean | false | Requires at least one token. |
clearable | boolean | false | Shows a clear action. |
disabled | boolean | false | Disables editing. |
readOnly | boolean | false | Prevents editing. |
size | xs | sm | default | default | Field density: extra small, small, or default. |
variant | outline | filled | outline | Visual style matching Input. |
fullWidth | boolean | false | Expands the field to its container width. |
leadingIcon, prefix | ReactNode | — | Content before the input. |
suffix, trailingIcon | ReactNode | — | Content after the input. |
onTrailingIconClick | () => void | — | Makes the trailing icon a keyboard-accessible button and handles clicks. |
trailingIconLabel | string | Input action | Accessible label for the trailing icon button. |
loading | boolean | false | Shows a loader and prevents editing. |
inputMode | text | numeric | decimal | tel | email | url | — | Preferred mobile keyboard. |
aria-label | string | — | Accessible name when no visible label is provided. |
name, id | string | — | Native form name and stable input id. |
autoComplete | string | — | Native autocomplete hint. |
onFocus, onBlur | native input callbacks | — | Native focus lifecycle callbacks. |
className | string | — | Class applied to the outer field wrapper. |
style | CSSProperties | — | Inline styles applied to the outer field wrapper. |
All other standard text-input attributes from InputHTMLAttributes<HTMLInputElement> are forwarded to the native input, except size, value, defaultValue, onChange, and placeholder, which use the mask-specific API above.