Mask Input
Formats as you type — card numbers, phone numbers, dates. Hands back the raw characters alongside the formatted text, so a form does not submit "(555) 010-9999" to an API expecting digits.
src/components/ui/mask-input.tsxAbout
From the component's own source, where it was written.
A text field that formats as you type — card numbers, phone numbers, dates.
The mask is a pattern of placeholders: # for a digit, A for a letter, * for either. Everything else is a literal that the component inserts.
Two details make the difference between a mask that helps and one that fights you. Deleting a literal deletes the character before it, so backspace over the space in "4242 4242" removes a digit rather than sticking. And the caller receives the raw value alongside the formatted one, because a form that submits "(555) 010-9999" to an API expecting digits has just moved the parsing problem downstream.
Install
npx astralyx-ui add mask-input
Usage
import { MaskInput } from '@/components/ui/mask-input'
<MaskInput mask="#### #### #### ####" onValueChange={(text, raw) => setCard(raw)} />Composer
Change the props and the source below follows.
<MaskInput mask="#### #### #### ####" onValueChange={handle} />Examples
Masks
<MaskInput mask="#### #### #### ####" /> <MaskInput mask="(###) ###-####" />
API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
MaskInput
Extends Omit<ComponentProps<'input'>, 'value' | 'defaultValue' | 'onChange' | 'size'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| mask | string | required | # a digit, A a letter, * either. Anything else is a literal the component inserts. |
| value | string | — | — |
| defaultValue | string | '' | — |
| onValueChange | (formatted: string, raw: string) => void | — | Both forms, so the display value and the submitted value can differ. |
| size | keyof typeof fieldSize | 'md' | — |
| variant | 'default' | 'secondary' | 'ghost' | 'default' | — |
| error | boolean | false | — |
Functions
| Function | Signature | Description |
|---|---|---|
| applyMask | (input: string, mask: string) => { formatted: string; raw: string; } | Apply the mask, returning the formatted text and the raw characters kept. |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| backspace | handled | Deleting into a literal removes the character before it, so backspace over the space in "4242 4242" takes a digit rather than sticking. |
| paste | handled | Characters that do not fit a slot are skipped rather than stopping the fill, so pasting "4242-4242" into a digits mask keeps the digits. |