Fluxo UIFluxo UIv0.4.1

MaskedInput

A controlled text input that enforces a character-by-character mask pattern. Supports digits, letters, alphanumeric slots, and arbitrary literal separators with full keyboard navigation.

Mask Syntax

Build a mask string using the reserved characters below. Any other character is treated as a fixed literal separator.

CharacterAcceptsExample slot
9Digit (0–9)5
aLetter (a–z, A–Z)B
*Alphanumeric (a–z, A–Z, 0–9)X3
otherFixed literal separator-, /, (, ) …

Phone Number

Mask (999) 999-9999 — digits only with formatted separators.

US Phone Number

value: ""  |  raw: ""
import { MaskedInput } from 'fluxo-ui';

const [phone, setPhone] = useState('');

<MaskedInput
  mask="(999) 999-9999"
  value={phone}
  onChange={(e) => setPhone(e.value)}
/>

Date

Mask 99/99/9999 — calendar date with slash separators.

Date (MM/DD/YYYY)

value: ""  |  raw: ""
<MaskedInput
  mask="99/99/9999"
  value={date}
  onChange={(e) => setDate(e.value)}
/>

Time

Mask 99:99 — 24-hour or 12-hour time input.

Time (HH:MM)

value: ""  |  raw: ""
<MaskedInput
  mask="99:99"
  value={time}
  onChange={(e) => setTime(e.value)}
/>

Social Security Number

Mask 999-99-9999 — SSN with dash separators.

SSN

value: ""  |  raw: ""
<MaskedInput
  mask="999-99-9999"
  value={ssn}
  onChange={(e) => setSsn(e.value)}
/>

Credit Card

Mask 9999 9999 9999 9999 — four groups of four digits separated by spaces.

Credit Card Number

value: ""  |  raw: ""
<MaskedInput
  mask="9999 9999 9999 9999"
  value={cc}
  onChange={(e) => setCc(e.value)}
/>

IPv4 Address

Mask 999.999.999.999 — four octet groups with dot separators.

IPv4 Address

value: ""  |  raw: ""
<MaskedInput
  mask="999.999.999.999"
  value={ip}
  onChange={(e) => setIp(e.value)}
/>

Alphanumeric — License Plate

Mask aaa-9999 — three letters, a dash, then four digits.

Vehicle License Plate

value: ""  |  raw: ""
<MaskedInput
  mask="aaa-9999"
  value={plate}
  onChange={(e) => setPlate(e.value)}
/>

Raw Value vs Masked Value

Use includeLiterals=false to receive only the typed digits/letters in onChange, without the separator characters.

includeLiterals comparison

onChange emits e.g. (123) 456-7890

onChange emits e.g. 1234567890

<MaskedInput
  mask="(999) 999-9999"
  includeLiterals={false}
  value={phone}
  onChange={(e) => setPhone(e.value)}
  onRawChange={(raw, masked) => console.log(raw, masked)}
/>

Pre-filled Value

Pass a value prop at mount time (raw or masked) and the component normalises it into the mask.

Pre-filled inputs

<MaskedInput mask="(999) 999-9999" value="5551234567" onChange={(e) => setPhone(e.value)} />
<MaskedInput mask="99/99/9999"     value="01/15/1990"     onChange={(e) => setDate(e.value)} />
<MaskedInput mask="9999 9999 9999 9999" value="4111111111111111" onChange={(e) => setCc(e.value)} />

States

Disabled and Read-only

<MaskedInput mask="(999) 999-9999" value={v} onChange={(e) => setV(e.value)} />
<MaskedInput mask="(999) 999-9999" value={v} onChange={(e) => setV(e.value)} disabled />
<MaskedInput mask="(999) 999-9999" value={v} onChange={(e) => setV(e.value)} readonly />
<MaskedInput mask="(999) 999-9999" value={v} onChange={(e) => setV(e.value)} required />

Custom Slot Character

Use slotChar to change the placeholder shown for empty editable slots (default is _).

Custom slotChar

<MaskedInput mask="(999) 999-9999" slotChar="#" value={v} onChange={(e) => setV(e.value)} />
<MaskedInput mask="99/99/9999"     slotChar="·" value={v} onChange={(e) => setV(e.value)} />

Keyboard Navigation

KeyBehaviour
Any valid charInsert into the current editable slot and advance cursor
BackspaceClear the slot to the left of the cursor
DeleteClear the slot under the cursor
← / →Jump to previous / next editable slot
HomeJump to the first editable slot
EndJump to the slot after the last filled character
TabDefault browser tab-focus behaviour (not intercepted)
PasteInsert pasted text character-by-character, skipping non-matching chars

Import

import { MaskedInput } from 'fluxo-ui';

Props

mask
string

Mask pattern. Use '9' for digit, 'a' for letter, '*' for alphanumeric, any other char as literal separator. Either mask or preset must be provided

preset
'phone' | 'phone-us' | 'phone-intl' | 'date' | 'date-us' | 'ssn' | 'credit-card' | 'zip' | 'zip-plus4' | 'time'

Built-in mask preset that auto-fills the mask and a SR-readable format hint

formatHint
string

Format hint string surfaced under the input and linked via aria-describedby. Auto-derived from preset when not provided

value
string

Current value (raw or masked — component normalises it)

onChange
(event: ComponentEvent<string>) => void

Called when the value changes

onRawChange
(raw: string, masked: string) => void

Called with the raw (unmasked) value alongside the masked display value

slotChar
string"_"

Character shown for empty mask slots

includeLiterals
booleantrue

Whether to include literal separator characters in the onChange value

error
string | boolean

Error message string (also marks invalid). Pass `true` to mark invalid without a visible message

invalid
boolean

Force the field into an invalid state without an error message

helperText
ReactNode

Helper text rendered under the input and linked via aria-describedby

placeholder
string

Placeholder text. Defaults to the mask itself

required
booleanfalse

Mark the input as required

readonly
booleanfalse

Make the input read-only

disabled
booleanfalse

Disable the input

autoFocus
booleanfalse

Auto-focus on mount

id
string

Unique id for the input element

Features

Flexible Mask Syntax

Use '9' for digits, 'a' for letters, '*' for alphanumeric, and any other char as a fixed separator

Raw Value Access

onRawChange gives you the unformatted value alongside the masked display string

Pre-filled Values

Pass a raw or masked value at mount time and the component normalises it automatically

Custom Slot Character

Replace the default underscore placeholder for empty slots with any character

Keyboard Navigation

Arrow keys, Home, End, Backspace, Delete, and paste all work with slot-aware behaviour

includeLiterals Control

Choose whether onChange emits separators (e.g. dashes, spaces) or raw characters only

Accessibility

Keyboard-only operable, ARIA attributes, and screen-reader-friendly slot announcements

Theming

Full dark/light + 5 brand themes via CSS variables — zero extra config