KQ-491 · MASK/FIELD
Mask Field
A text field that wears its format. Ghost glyphs hold the shape of what is expected, and as characters land the mask's separators arrive on flick — scaling up from 0.6 as the ink comes in — while deleting pulls them back out the same way. One real input carries the value beneath a transparent text layer so a monospace cell grid can draw the glyphs, which keeps the native keyboard intact: typing, backspace across a separator, selection and paste all behave as the browser intends, and a pasted number fills every slot in a single cascade inside the 600ms budget.
Waylight sign-in — paste a full number to watch every slot fill at once.
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/mask-field
Props
- mask
- string
- default —
- The shape, with # for a digit and A for a letter, e.g. "(###) ###-####" or "#### #### #### ####".
- value / defaultValue
- string
- default —
- Raw characters, without separators — controlled or initial.
- onValueChange
- (raw: string, formatted: string) => void
- default —
- Both readings on every change.
- label
- string
- default —
- Visible label above the box.
- placeholderChar
- string
- default "_"
- The ghost glyph standing in for an empty slot.
| Prop | Type | Default | Description |
|---|---|---|---|
| mask | string | — | The shape, with # for a digit and A for a letter, e.g. "(###) ###-####" or "#### #### #### ####". |
| value / defaultValue | string | — | Raw characters, without separators — controlled or initial. |
| onValueChange | (raw: string, formatted: string) => void | — | Both readings on every change. |
| label | string | — | Visible label above the box. |
| placeholderChar | string | "_" | The ghost glyph standing in for an empty slot. |