- 🎯 Simple API
- 💎 Works like a charm with Next.js
- ✨ Compatible with React Hook Form
- 🏁 Compatible with React Final Form
npm i use-mask-inputimport React from 'react' import { withMask } from 'use-mask-input'; const App = () => { return ( <input type="text" ref={withMask('9999-9999')} /> ) }import React from 'react'; import { useForm } from 'react-hook-form'; import { useHookFormMask } from 'use-mask-input'; function App() { const { register, handleSubmit } = useForm(); const registerWithMask = useHookFormMask(register); ... return ( <form onSubmit={onSubmit}> <input {...registerWithMask("phone", ['99 9999-9999', '99999-9999'], { required: true })} type="text" /> <button type="submit">Submit</button> </form> ); }Just use withMask normaly.
import React from 'react'; import { Form, Field } from 'react-final-form'; import { withMask } from 'use-mask-input'; function App() { ... return ( <Form onSubmit={onSubmit} render={({ handleSubmit }) => ( <form onSubmit={handleSubmit}> <Field name="phone" render={({ input, meta }) => ( <input ref={withMask('9999-9999')} {...input} /> )} /> <button type="submit">Submit</button> </form> )} /> ); }The mask params can be
These are the very basics of masking. The mask is defined and will not change during the input.
<input {...registerWithMask("phone", '99 9999-9999')} type="text" />It is possible to define some parts in the mask as optional. This is done by using [ ]. By example:
<input {...registerWithMask("phone", '99 [9]9999-9999')} type="text" />This mask will allow input like (99) 99999-9999 or (99) 9999-9999.
Dynamic masks can change during input. To define a dynamic part use { }.
{n} => n repeats {n|j} => n repeats, with j jitmasking {n,m} => from n to m repeats {n,m|j} => from n to m repeats, with j jitmasking
Also {+} and {} is allowed. + start from 1 and start from 0.
By example:
//static mask with dynamic syntax <input {...registerWithMask("phone", "aa-9{4}")} type="text" /> // dynamic mask ~ the 9 def can be occur 1 to 4 times <input {...registerWithMask("phone", "aa-9{4}")} type="text" /> // dynamic mask ~ email <input {...registerWithMask("phone", "*{1,20}[.*{1,20}][.*{1,20}][.*{1,20}]@*{1,20}[.*{2,6}][.*{1,2}]")} type="text" />A Lot of common default "aliases" presets, you can use like that:
<input // the alias {...registerWithMask("date", "datetime", { inputFormat: "yyyy-mm-dd", })} type="text" />You can use together with options like inputFormat, prefix, suffix, etc. Checkout API docs
The avaliable ones is:
datetimeemailipdatetimecpfemailnumericcurrencydecimalintegerpercentageurlipmacssn
The alternator syntax is like an OR statement. The mask can be one of the 3 choices specified in the alternator.
To define an alternator use the |. ex: "a|9" => a or 9 "(aaa)|(999)" => aaa or 999 "(aaa|999|9AA)" => aaa or 999 or 9AA "aaaa|9999" => aaa a or 9 999
<input {...registerWithMask("phone", "9999-9999|99999-9999")} type="text" /> // or just passing an array <input {...registerWithMask("phone", ["9999-9999", "99999-9999"])} type="text" />You can define the mask as a function that can allow you to preprocess the resulting mask. Example sorting for multiple masks or retrieving mask definitions dynamically through ajax. The preprocessing fn should return a valid mask definition.
<input {...registerWithMask("phone", function () { /* do stuff */ return ["[1-]AAA-999", "[1-]999-AAA"]; })} type="text" />Attach a mask to an input via a ref:
const attach = withMask('999-9999', { clearIncomplete: true }); <input ref={attach} />;- mask:
string|string[]|(opts: Options) => string \| string[] - options:
Options(see below)
Integrate masking with React-Hook-Form’s register:
const maskedRegister = useHookFormMask(register); <input {...maskedRegister('phone', '999-9999', { showMaskOnFocus: true })} />;| Option | Description | Type | Default |
|---|---|---|---|
mask | Static mask, array of masks, or function returning mask(s) | string | string[] | fn | — |
regex | Treat the mask as a regular expression | string | — |
placeholder | Character shown for empty slots | string | "_" |
optionalmarker | Delimiters for optional sections | { start: string; end: string } | { start: "[", end: "]" } |
quantifiermarker | Delimiters for repetition ranges | { start: string; end: string } | { start: "{", end: "}" } |
groupmarker | Delimiters for grouping | { start: string; end: string } | { start: "(", end: ")" } |
alternatormarker | Character separating alternator options | string | `" |
escapeChar | Character to escape mask meta-symbols | string | "\\" |
definitions | Custom symbol→validator mappings | Record<string,Definition> | — |
alias | Built-in preset (“datetime”, “currency”, etc.) | string | — |
inputFormat | Format string for datetime alias | string | — |
outputFormat | Format of unmasked datetime value | string | — |
displayFormat | Visual format when losing focus (datetime alias) | string | — |
clearMaskOnLostFocus | Trim placeholders on blur | boolean | true |
showMaskOnFocus | Show full mask when focused | boolean | true |
showMaskOnHover | Show mask when hovering | boolean | true |
clearIncomplete | Clear input if not fully filled on blur | boolean | false |
removeMaskOnSubmit | Strip mask chars on form submit | boolean | false |
autoUnmask | Always return unmasked value | boolean | false |
jitMasking | Just-in-time masking (only show entered chars) | boolean | false |
nullable | Return "" if no input | boolean | true |
noValuePatching | Disable .value patching hacks | boolean | false |
insertMode | Insert vs overwrite | boolean | true |
insertModeVisual | Highlight caret in overwrite mode | boolean | true |
positionCaretOnClick | Caret placement on click: "none", "lvp", "radixFocus", "select", "ignore" | string | "lvp" |
positionCaretOnTab | Move caret to last valid position on Tab | boolean | true |
tabThrough | Tab between mask sections | boolean | false |
skipOptionalPartCharacter | Character to skip optional blocks | string | " " |
numericInput | Keep caret at end for numeric | boolean | false |
rightAlign | Right-align numeric | boolean | true |
radixPoint | Decimal separator | string | "" |
groupSeparator | Thousands separator | string | "" |
digits | Fractional digits count or range | number | string | "*" |
digitsOptional | Allow skipping fractional digits | boolean | true |
enforceDigitsOnBlur | Force show fractional digits on blur | boolean | false |
allowMinus | Permit minus sign | boolean | true |
negationSymbol | Symbols for negative (e.g. { front: "-", back: "" }) | object | { front: "-", back: "" } |
prefix | Static text prepended | string | "" |
suffix | Static text appended | string | "" |
SetMaxOnOverflow | Clamp value at max if exceeded | boolean | false |
min | Minimum allowed (numeric/datetime) | string | number | — |
max | Maximum allowed (numeric/datetime) | string | number | — |
step | Ctrl+↑/↓ increment step (numeric) | number | 1 |
repeat | Repeat mask N times or "*" for infinite | number | string | 0 |
greedy | Greedy vs non-greedy repeat | boolean | false |
keepStatic | Delay switching in alternator/multi-mask scenarios | boolean | null | (multi-mask: true) |
importDataAttributes | Read HTML data-inputmask-* attrs | boolean | true |
supportsInputType | Allow masking on specified inputmode types | string[] | ["text","tel","url","password","search"] |
ignorables | Key codes to ignore | number[] | — |
prefillYear | Pre-fill century in datetime alias | boolean | true |
casing | Force letter casing: "upper", "lower", "title" | string | — |
inputmode | Hint for on-screen keyboards (HTML inputmode) | string | "verbatim" |