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.tsx

About

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.

Props
tsx
<MaskInput mask="#### #### #### ####" onValueChange={handle} />

Examples

Masks

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'>.

PropTypeDefaultDescription
maskstringrequired# a digit, A a letter, * either. Anything else is a literal the component inserts.
valuestring——
defaultValuestring''—
onValueChange(formatted: string, raw: string) => void—Both forms, so the display value and the submitted value can differ.
sizekeyof typeof fieldSize'md'—
variant'default' | 'secondary' | 'ghost''default'—
errorbooleanfalse—

Functions

FunctionSignatureDescription
applyMask(input: string, mask: string) => { formatted: string; raw: string; }Apply the mask, returning the formatted text and the raw characters kept.

Behaviour

TopicDetailDescription
backspacehandledDeleting into a literal removes the character before it, so backspace over the space in "4242 4242" takes a digit rather than sticking.
pastehandledCharacters that do not fit a slot are skipped rather than stopping the fill, so pasting "4242-4242" into a digits mask keeps the digits.