# use-mask-input — Full Documentation > Complete documentation for use-mask-input, a React hook library for input masks. Compatible with plain React, React Hook Form, TanStack Form, and Ant Design. This file aggregates all documentation pages into a single document optimized for LLM ingestion. For a shorter overview, see [llm.txt](./llm.txt). --- # use-mask-input
npm version bundle size npm downloads
Input masks for React. Works with plain inputs, React Hook Form, TanStack Form, and Ant Design. ```bash npm install use-mask-input ``` ```tsx import { useMaskInput } from 'use-mask-input'; function PhoneInput() { const ref = useMaskInput({ mask: '(99) 99999-9999' }); return ; } ``` ## With React Hook Form ```tsx import { useForm } from 'react-hook-form'; import { useHookFormMask } from 'use-mask-input'; function MyForm() { const { register, handleSubmit } = useForm(); const registerWithMask = useHookFormMask(register); return (
); } ``` ## With TanStack Form ```tsx import { useForm } from '@tanstack/react-form'; import { useTanStackFormMask } from 'use-mask-input'; function MyForm() { const maskField = useTanStackFormMask(); const form = useForm({ defaultValues: { phone: '' }, onSubmit: async ({ value }) => console.log(value), }); return (
{ event.preventDefault(); event.stopPropagation(); void form.handleSubmit(); }} > {(field) => { const inputProps = maskField( '(99) 99999-9999', { name: field.name, value: field.state.value, onBlur: field.handleBlur, onChange: (event) => field.handleChange(event.target.value), }, ); return ; }}
); } ``` See the full [TanStack Form Integration](./tanstack-form) guide. ## With Ant Design ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function EmailInput() { const ref = useMaskInputAntd({ mask: 'email' }); return ; } ``` See the full [Ant Design Integration](./antd) guide. ## APIs | API | When to use | |-----|-------------| | [`useMaskInput`](./api-reference#usemaskinput) | Default choice. Returns a ref callback. | | [`useHookFormMask`](./api-reference#usehookformmask) | Wraps React Hook Form's `register`. | | [`useTanStackFormMask`](./api-reference#usetanstackformmask) | Wraps TanStack Form input props with mask support. | | [`withMask`](./api-reference#withmask) | Non-hook ref callback. **Requires `React.memo`.** | | [`withHookFormMask`](./api-reference#withhookformmask) | Non-hook mask for registered fields. **Requires `React.memo`.** | | [`withTanStackFormMask`](./api-reference#withtanstackformmask) | Non-hook mask for TanStack input props. **Requires `React.memo`.** | | [`useMaskInputAntd`](./api-reference#usemaskinputantd) | `useMaskInput` for Ant Design. | | [`useHookFormMaskAntd`](./api-reference#usehookformmaskantd) | `useHookFormMask` for Ant Design. | Full signatures and parameters in the [API Reference](./api-reference). ## Mask Types - [Static Mask](./tutorial-basics/static-mask): fixed patterns like `999-999` - [Dynamic Mask](./tutorial-basics/dynamic-mask): variable-length patterns - [Optional Mask](./tutorial-basics/optional-mask): masks with optional parts - [Alias Mask](./tutorial-basics/alias-mask): built-in presets (`email`, `currency`, `datetime`, ...) - [Alternator Mask](./tutorial-basics/alternator-mask): multiple patterns - [Preprocessing Mask](./tutorial-basics/preprocessing-mask): dynamic masks with functions --- # API Reference **use-mask-input** exports six main APIs and two Ant Design-specific hooks. Choose the one that fits your use case: | API | Type | React Hook Form | Ant Design | Needs `memo`? | |-----|------|:---------------:|:----------:|:-------------:| | [`useMaskInput`](#usemaskinput) | Hook | - | - | No | | [`useHookFormMask`](#usehookformmask) | Hook | Yes | - | No | | [`useTanStackFormMask`](#usetanstackformmask) | Hook | - | - | No | | [`withMask`](#withmask) | Function | - | - | **Yes** | | [`withHookFormMask`](#withhookformmask) | Function | Yes | - | **Yes** | | [`withTanStackFormMask`](#withtanstackformmask) | Function | - | - | **Yes** | | [`useMaskInputAntd`](#usemaskinputantd) | Hook | - | Yes | No | | [`useHookFormMaskAntd`](#usehookformmaskantd) | Hook | Yes | Yes | No | ## Hooks Hooks manage ref stability internally (`useCallback` / `useMemo`), so they are safe to use in components that re-render frequently without any extra precautions. ### useMaskInput React hook that returns a ref callback for applying an input mask. ```ts function useMaskInput(props: { mask: Mask; register?: (element: HTMLElement) => void; options?: Options; }): (input: HTMLElement | null) => void ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `register` | `(element: HTMLElement) => void` | No | Callback that receives the resolved DOM element (useful for third-party form libraries). | | `options` | `Options` | No | Inputmask configuration options (placeholder, autoUnmask, etc.). | **Returns** A stable ref callback. Attach it to any `` (or compatible element) via the `ref` prop. The returned callback also exposes `unmaskedValue()` so you can read the current unmasked value directly from the hook result. **Example** ```tsx import { useMaskInput } from 'use-mask-input'; function PhoneInput() { const maskRef = useMaskInput({ mask: '(99) 99999-9999', }); return ; } ``` ### useHookFormMask React hook that wraps React Hook Form's `register` and adds automatic masking. ```ts function useHookFormMask( registerFn: UseFormRegister ): ( fieldName: Path, mask: Mask, options?: RegisterOptions & Options ) => UseHookFormMaskReturn ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `registerFn` | `UseFormRegister` | Yes | The `register` function returned by `useForm()`. | **Returns** A function with the signature `(fieldName, mask, options?) => { ref, name, onChange, onBlur, ... }`. Use it by spreading the result onto your input. The returned object also exposes `unmaskedValue()` for the resolved field. **Example** ```tsx import { useForm } from 'react-hook-form'; import { useHookFormMask } from 'use-mask-input'; function MyForm() { const { register, handleSubmit } = useForm(); const registerWithMask = useHookFormMask(register); return (
{/* Fields without masks still use the regular register */}
); } ``` ### useTanStackFormMask React hook that wraps TanStack Form-compatible input props and adds automatic masking. ```ts function useTanStackFormMask(): ( mask: Mask, inputProps: T, options?: Options ) => UseTanStackFormMaskReturn ``` **Parameters** The returned function accepts: | Name | Type | Required | Description | |------|------|:--------:|-------------| | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `inputProps` | `TanStackFormInputProps` | Yes | Input props generated from TanStack `field` state and handlers. | | `options` | `Options` | No | Inputmask configuration options. | **Returns** A new props object with a masked `ref` callback while preserving all original handlers and values. **Example** ```tsx import { useForm } from '@tanstack/react-form'; import { useTanStackFormMask } from 'use-mask-input'; function MyForm() { const maskField = useTanStackFormMask(); const form = useForm({ defaultValues: { phone: '' }, onSubmit: async ({ value }) => console.log(value), }); return ( {(field) => { const inputProps = maskField( '(99) 99999-9999', { name: field.name, value: field.state.value, onBlur: field.handleBlur, onChange: (event) => field.handleChange(event.target.value), }, ); return ; }} ); } ``` ## Higher-Order Functions `withMask` and `withHookFormMask` are **not** hooks. They are plain functions that create new ref callbacks on every call. Because React treats a new ref callback as a different ref, calling these directly inside a component body causes the mask to be re-applied on every render. :::warning Wrap the component with `React.memo` Since `withMask` and `withHookFormMask` are not hooks, they don't have internal memoization via React's lifecycle. You **must** wrap the component that uses them with `React.memo` to ensure the ref callback identity stays stable across parent re-renders. Without `memo`, every parent re-render creates a new ref callback, which detaches and re-attaches the mask. This causes flickering, cursor position loss, and degraded performance. ::: ### withMask Creates a ref callback that applies an input mask. This is the simplest API when you just need a masked ref and don't use React Hook Form. ```ts function withMask( mask: Mask, options?: Options ): (input: HTMLElement | null) => void ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `options` | `Options` | No | Inputmask configuration options. | **Returns** A ref callback function to pass to an element's `ref` prop. The returned callback also exposes `unmaskedValue()`. **Caching behavior**: when called without `options`, the callback is cached by mask key so the same function identity is returned for the same mask. When `options` is provided, a new callback is created each call, so `memo` is needed. **Example** ```tsx import { memo } from 'react'; import { withMask } from 'use-mask-input'; const PhoneInput = memo(() => { return ( ); }); ``` **With options** ```tsx import { memo } from 'react'; import { withMask } from 'use-mask-input'; const CurrencyInput = memo(() => { return ( ); }); ``` :::tip Prefer `useMaskInput` if you don't need the function-based API If you're already inside a component and don't need to pass the mask as a prop, `useMaskInput` is the safer choice. It handles memoization internally and doesn't require `memo`. ::: ### withHookFormMask Takes an already-registered React Hook Form field and adds mask support to it. ```ts function withHookFormMask( register: UseFormRegisterReturn, mask: Mask, options?: Options ): UseHookFormMaskReturn ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `register` | `UseFormRegisterReturn` | Yes | The object returned by calling `register('fieldName')`. | | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `options` | `Options` | No | Inputmask and/or React Hook Form register options. | **Returns** A new register return object with the `ref` replaced by a mask-applying ref callback. Spread it onto your input. The returned object also exposes `unmaskedValue()`. **Example** ```tsx import { memo } from 'react'; import { useForm } from 'react-hook-form'; import { withHookFormMask } from 'use-mask-input'; const MyForm = memo(() => { const { register, handleSubmit } = useForm(); return (
); }); ``` :::tip Prefer `useHookFormMask` for most cases `useHookFormMask` is a hook that wraps `register` with built-in memoization. Use `withHookFormMask` only when you need to apply the mask to an already-registered field (e.g., the `register` call happens elsewhere and you receive the return object as a prop). ::: ### withTanStackFormMask Takes TanStack Form-compatible input props and adds mask support to them. ```ts function withTanStackFormMask( inputProps: T, mask: Mask, options?: Options ): UseTanStackFormMaskReturn ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `inputProps` | `TanStackFormInputProps` | Yes | Input props object from TanStack field state and handlers. | | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `options` | `Options` | No | Inputmask configuration options. | **Returns** A new input props object with `ref` replaced by a mask-applying callback. **Example** ```tsx import { memo } from 'react'; import { withTanStackFormMask } from 'use-mask-input'; const InputField = memo(function InputField({ inputProps, }: { inputProps: { name: string; value: string; onBlur: () => void; onChange: (event: React.ChangeEvent) => void; }; }) { const maskedProps = withTanStackFormMask(inputProps, '(99) 99999-9999'); return ; }); ``` ## Ant Design Hooks These hooks handle Ant Design's `InputRef` structure automatically. Import them from `use-mask-input/antd`. ### useMaskInputAntd React hook for applying masks to Ant Design `Input` components. ```ts import { useMaskInputAntd } from 'use-mask-input/antd'; function useMaskInputAntd(props: { mask: Mask; register?: (element: HTMLElement) => void; options?: Options; }): (input: InputRef | null) => void ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `register` | `(element: HTMLElement) => void` | No | Callback that receives the resolved DOM element. | | `options` | `Options` | No | Inputmask configuration options. | **Returns** A stable ref callback that accepts Ant Design's `InputRef` and applies the mask to the underlying input element. The returned callback also exposes `unmaskedValue()`. **Example** ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function PhoneInput() { const maskRef = useMaskInputAntd({ mask: '(99) 99999-9999' }); return ; } ``` See the full [Ant Design Integration](./antd) guide for Form.Item, useWatch, and validation examples. ### useHookFormMaskAntd Combines React Hook Form with Ant Design. A masked `register` that works with `InputRef`. ```ts import { useHookFormMaskAntd } from 'use-mask-input/antd'; function useHookFormMaskAntd( registerFn: UseFormRegister ): ( fieldName: Path, mask: Mask, options?: RegisterOptions & Options ) => UseHookFormMaskAntdReturn ``` **Parameters** | Name | Type | Required | Description | |------|------|:--------:|-------------| | `registerFn` | `UseFormRegister` | Yes | The `register` function returned by `useForm()`. | **Returns** A function with the signature `(fieldName, mask, options?)` that returns an object you spread onto Ant Design's `Input`. **Example** ```tsx import { Input } from 'antd'; import { useForm } from 'react-hook-form'; import { useHookFormMaskAntd } from 'use-mask-input/antd'; function MyForm() { const { register, handleSubmit } = useForm(); const registerWithMask = useHookFormMaskAntd(register); return (
); } ``` ## Types ### Mask ```ts type Mask = | 'datetime' | 'email' | 'numeric' | 'currency' | 'decimal' | 'integer' | 'percentage' | 'url' | 'ip' | 'mac' | 'ssn' | 'brl-currency' | 'cpf' | 'cnpj' | 'br-bank-account' | 'br-bank-agency' | (string & {}) // custom pattern like '999-999' | (string[] & {}) // dynamic mask array | null; // no mask ``` ### Options Inputmask configuration options. Commonly used: | Option | Type | Description | |--------|------|-------------| | `placeholder` | `string` | Placeholder character for unfilled positions (default `_`). | | `autoUnmask` | `boolean` | If `true`, `value` returns unmasked data. | | `prefix` | `string` | Text prepended to the input. | | `suffix` | `string` | Text appended to the input. | | `radixPoint` | `string` | Decimal separator character. | | `groupSeparator` | `string` | Thousands separator character. | | `digits` | `number` | Number of decimal digits. | | `rightAlign` | `boolean` | Align input text to the right. | | `inputFormat` | `string` | Date input format (for `datetime` alias). | | `outputFormat` | `string` | Date output format (for `datetime` alias). | | `min` | `number` | Minimum allowed value (numeric aliases). | | `max` | `number` | Maximum allowed value (numeric aliases). | For the complete list, see the [Inputmask documentation](https://robinherbots.github.io/Inputmask/). ### Input ```ts type Input = HTMLInputElement | HTMLTextAreaElement | HTMLElement; ``` ### TanStackFormInputProps ```ts interface TanStackFormInputProps { name?: string; ref?: RefCallback; [key: string]: unknown; } ``` ### UseTanStackFormMaskReturn ```ts type UseTanStackFormMaskReturn = Omit & { ref: RefCallback; prevRef: RefCallback | undefined; }; ``` --- # Static Mask Static masks are the foundation of input masking. They have a fixed pattern that doesn't change during user input. This is the simplest and most commonly used type of mask. ## Basic Usage A static mask is defined as a string where each character represents a specific input pattern: ```tsx import { useMaskInput } from 'use-mask-input'; function PhoneInput() { const phoneMask = useMaskInput({ mask: '9999-9999', }); return ( ); } ``` ## Mask Definitions The library uses special characters to define input patterns: - `9` - Numeric digit (0-9) - `a` - Alphabetic character (a-z, A-Z) - `*` - Alphanumeric character (a-z, A-Z, 0-9) - `A` - Uppercase alphabetic character - `#` - Hexadecimal character (0-9, a-f, A-F) ## Common Examples ### Phone Number ```tsx function PhoneInput() { const phoneMask = useMaskInput({ mask: '(99) 99999-9999', }); return ( ); } ``` ### Date ```tsx function DateInput() { const dateMask = useMaskInput({ mask: '99/99/9999', }); return ( ); } ``` ### Credit Card ```tsx function CreditCardInput() { const cardMask = useMaskInput({ mask: '9999 9999 9999 9999', }); return ( ); } ``` ### License Plate (Brazil) ```tsx function LicensePlateInput() { const plateMask = useMaskInput({ mask: 'AAA-9999', }); return ( ); } ``` ### ZIP Code ```tsx function ZipCodeInput() { const zipMask = useMaskInput({ mask: '99999-999', }); return ( ); } ``` ## Custom Characters You can also use literal characters in your mask. Any character that isn't a mask definition will be treated as a literal and displayed as-is: ```tsx function CustomInput() { const customMask = useMaskInput({ mask: 'ID: 999-AAA', }); return ( ); } ``` ## Tips - Static masks are perfect for fixed-format inputs like phone numbers, dates, and IDs - Literal characters (like `-`, `(`, `)`, `/`) are automatically included in the mask - The mask pattern is case-sensitive for alphabetic characters - Use `A` for uppercase-only and `a` for case-insensitive alphabetic input --- # Dynamic Mask Dynamic masks allow the mask pattern to change or repeat during input. This is useful for inputs where the length or pattern can vary, like email addresses or variable-length numbers. ## Basic Syntax Use curly braces `{ }` to define dynamic parts: - `{n}` - Exactly n repetitions - `{n|j}` - n repetitions with jit masking - `{n,m}` - From n to m repetitions - `{n,m|j}` - From n to m repetitions with jit masking - `{+}` - One or more repetitions (starts from 1) - `{}` - Zero or more repetitions (starts from 0) ## Common Examples ### Fixed Repetition ```tsx import { useMaskInput } from 'use-mask-input'; function FixedLengthInput() { const mask = useMaskInput({ mask: 'aa-9{4}', }); return ( ); } ``` This mask requires exactly 4 digits after the letters. ### Variable Length ```tsx function VariableLengthInput() { const mask = useMaskInput({ mask: '9{1,10}', }); return ( ); } ``` Accepts 1 to 10 digits. ### Email Address ```tsx function EmailInput() { const emailMask = useMaskInput({ mask: '*{1,20}[.*{1,20}][.*{1,20}][.*{1,20}]@*{1,20}[.*{2,6}][.*{1,2}]', }); return ( ); } ``` This creates a flexible email mask that accepts: - Local part: 1-20 alphanumeric characters - Optional subdomains: up to 3 levels - Domain: 1-20 alphanumeric characters - TLD: 2-6 characters with optional country code ### One or More Characters ```tsx function OneOrMoreInput() { const mask = useMaskInput({ mask: 'A{+}', }); return ( ); } ``` Accepts one or more uppercase letters. ### Zero or More Characters ```tsx function ZeroOrMoreInput() { const mask = useMaskInput({ mask: '9{}', }); return ( ); } ``` Accepts zero or more digits. ### Product Code ```tsx function ProductCodeInput() { const mask = useMaskInput({ mask: 'A{2}-9{4,8}', }); return ( ); } ``` Requires 2 letters followed by 4 to 8 digits. ### Flexible ID ```tsx function FlexibleIdInput() { const mask = useMaskInput({ mask: 'ID-9{3,6}-A{1,3}', }); return ( ); } ``` Accepts: - `ID-123-A` - `ID-12345-ABC` - `ID-123456-AB` ## JIT Masking JIT (Just-In-Time) masking shows the mask only as the user types: ```tsx function JitMaskInput() { const mask = useMaskInput({ mask: '9{4|1}', options: { jitMasking: true, }, }); return ( ); } ``` ## Tips - Use dynamic masks for inputs with variable lengths - Combine with optional sections for maximum flexibility - JIT masking provides a better user experience for long inputs - Dynamic masks are perfect for email, URLs, and flexible ID formats --- # Optional Mask Optional masks allow certain parts of the mask to be optional. This is useful when you want to accept inputs with or without specific parts, like area codes in phone numbers. ## Basic Syntax Use square brackets `[ ]` to define optional parts of the mask: ```tsx import { useMaskInput } from 'use-mask-input'; function PhoneInput() { const phoneMask = useMaskInput({ mask: '99 [9]9999-9999', }); return ( ); } ``` This mask will accept both: - `(99) 99999-9999` (with area code) - `(99) 9999-9999` (without area code) ## Common Examples ### Phone Number with Optional Area Code ```tsx function PhoneInput() { const phoneMask = useMaskInput({ mask: '[99] 9999-9999', }); return ( ); } ``` Users can type: - `11 98765-4321` (with area code) - `98765-4321` (without area code) ### Email with Optional Domain ```tsx function EmailInput() { const emailMask = useMaskInput({ mask: '*{1,20}[.*{1,20}][.*{1,20}][.*{1,20}]@*{1,20}[.*{2,6}][.*{1,2}]', }); return ( ); } ``` ### Credit Card with Optional Spaces ```tsx function CreditCardInput() { const cardMask = useMaskInput({ mask: '9999[ 9999][ 9999][ 9999]', }); return ( ); } ``` ### International Phone Number ```tsx function InternationalPhoneInput() { const phoneMask = useMaskInput({ mask: '[+99] [9]9999-9999', }); return ( ); } ``` This accepts: - `+55 1198765-4321` (with country code and area code) - `55 1198765-4321` (without +) - `1198765-4321` (without country code) ## Multiple Optional Sections You can have multiple optional sections in a single mask: ```tsx function FlexibleInput() { const flexibleMask = useMaskInput({ mask: '[Prefix-]999[-Suffix]', }); return ( ); } ``` ## Tips - Optional sections are skipped when the user doesn't type the required characters - Use optional masks when you want to support multiple input formats - Combine optional sections with dynamic masks for maximum flexibility - The optional marker characters `[` and `]` can be customized via options --- # Alias Mask Alias masks provide pre-configured masks for common use cases like dates, currency, email, and more. They save you from writing complex mask patterns manually. ## Available Aliases The library includes the following built-in aliases: - `datetime` - Date and time formatting - `email` - Email address validation - `ip` - IP address (IPv4) - `cpf` - Brazilian CPF (tax ID) - `cnpj` - Brazilian CNPJ (company tax ID) - `br-bank-account` - Brazilian bank account numbers (multiple formats) - `br-bank-agency` - Brazilian bank agency numbers - `numeric` - Numeric input - `currency` - Currency formatting - `brl-currency` - Brazilian Real (R$) currency - `decimal` - Decimal numbers - `integer` - Integer numbers - `percentage` - Percentage values - `url` - URL formatting - `mac` - MAC address - `ssn` - Social Security Number ## Basic Usage Simply use the alias name as the mask: ```tsx import { useMaskInput } from 'use-mask-input'; function DateInput() { const dateMask = useMaskInput({ mask: 'datetime', options: { inputFormat: 'dd/mm/yyyy', }, }); return ( ); } ``` ## Common Examples ### Date and Time ```tsx function DateTimeInput() { const dateTimeMask = useMaskInput({ mask: 'datetime', options: { inputFormat: 'dd/mm/yyyy HH:MM', outputFormat: 'yyyy-mm-dd HH:MM', }, }); return ( ); } ``` If you need the `outputFormat` value, read it from `dateTimeMask.unmaskedValue()`. The visible input value stays masked, so `e.target.value` is not the unmasked output. ### Email ```tsx function EmailInput() { const emailMask = useMaskInput({ mask: 'email', }); return ( ); } ``` ### Currency ```tsx function CurrencyInput() { const currencyMask = useMaskInput({ mask: 'currency', options: { prefix: 'R$ ', groupSeparator: '.', radixPoint: ',', digits: 2, }, }); return ( ); } ``` ### IP Address ```tsx function IpAddressInput() { const ipMask = useMaskInput({ mask: 'ip', }); return ( ); } ``` ### Payment card number ```tsx function CardNumberInput() { const cardMask = useMaskInput({ mask: '9999 9999 9999 9999', }); return ( ); } ``` ### Company tax ID (example) Some regions ship dedicated aliases (for example `cnpj` in Brazil). Prefer a custom pattern when you need a format that is not built in. ```tsx function CompanyIdInput() { const idMask = useMaskInput({ mask: '99.999.999/9999-99', }); return ( ); } ``` ### Brazilian Bank Account Automatically handles multiple bank account formats supporting Bradesco, Itaú, Banco do Brasil, Caixa Econômica, Nubank, and other Brazilian banks. #### Basic Usage ```tsx function BankAccountInput() { const bankAccountMask = useMaskInput({ mask: 'br-bank-account', }); return ( ); } ``` #### Supported Formats The mask automatically adapts to different bank account number formats: ```tsx function BankAccountInput() { const bankAccountMask = useMaskInput({ mask: 'br-bank-account', }); return ( ); } ``` **Supported formats:** - `1234567-9` (Bradesco, Stone, Next) - `12345678-9` (BB, Santander, Safra) - `123456789-9` (Itaú, Inter, Sicoob) - `1234567890-1` (Nubank, Neon, Mercado Pago) - `(001)12345678-9` (Caixa Econômica) - `123456` or `1234567` (optional separator for Agibank, BV) **Example with placeholder customization:** ```tsx function BankAccountInput() { const bankAccountMask = useMaskInput({ mask: 'br-bank-account', }); return ( ); } ``` ### Brazilian Bank Agency Automatically handles bank agency numbers for major Brazilian banks. #### Basic Usage ```tsx function BankAgencyInput() { const bankAgencyMask = useMaskInput({ mask: 'br-bank-agency', }); return ( ); } ``` #### Supported Formats Bank agency numbers typically range from 3 to 5 digits, commonly formatted as: - `0000` (4 digits - most common) - `000` (3 digits) - `00000` (5 digits) **Example with placeholder customization:** ```tsx function BankAgencyInput() { const bankAgencyMask = useMaskInput({ mask: 'br-bank-agency', }); return ( ); } ``` ### Numeric Input ```tsx function NumericInput() { const numericMask = useMaskInput({ mask: 'numeric', options: { min: 0, max: 1000, }, }); return ( ); } ``` ### Decimal Numbers ```tsx function DecimalInput() { const decimalMask = useMaskInput({ mask: 'decimal', options: { digits: 2, radixPoint: ',', groupSeparator: '.', }, }); return ( ); } ``` ### Percentage ```tsx function PercentageInput() { const percentageMask = useMaskInput({ mask: 'percentage', options: { digits: 2, suffix: ' %', }, }); return ( ); } ``` ### URL ```tsx function UrlInput() { const urlMask = useMaskInput({ mask: 'url', }); return ( ); } ``` ### MAC Address ```tsx function MacAddressInput() { const macMask = useMaskInput({ mask: 'mac', }); return ( ); } ``` ## Tips - Aliases provide a quick way to implement common input formats - Most aliases accept additional options for customization - Use aliases when you need standard formatting patterns - Combine alias options with custom configurations for specific requirements --- # Alternator Mask Alternator masks allow you to define multiple mask patterns, where the input can match any one of them. This is like an OR condition - the mask can be one of several choices. ## Basic Syntax Use the pipe character `|` to separate alternator options: ```tsx import { useMaskInput } from 'use-mask-input'; function PhoneInput() { const phoneMask = useMaskInput({ mask: '9999-9999|99999-9999', }); return ( ); } ``` This mask accepts both: - `1234-5678` (8 digits) - `12345-6789` (9 digits) ## Using Arrays You can also pass an array of masks instead of using the pipe syntax: ```tsx function PhoneInput() { const phoneMask = useMaskInput({ mask: ['9999-9999', '99999-9999'], }); return ( ); } ``` ## Common Examples ### Phone Numbers (Landline vs Mobile) ```tsx function PhoneInput() { const phoneMask = useMaskInput({ mask: '(99) 9999-9999|(99) 99999-9999', }); return ( ); } ``` Accepts both landline (8 digits) and mobile (9 digits) formats. ### Credit Card Types ```tsx function CreditCardInput() { const cardMask = useMaskInput({ mask: [ '9999 9999 9999 9999', // Visa, Mastercard '9999 999999 99999', // Amex ], }); return ( ); } ``` ### Date Formats ```tsx function DateInput() { const dateMask = useMaskInput({ mask: '99/99/9999|99-99-9999|99.99.9999', }); return ( ); } ``` Accepts dates with `/`, `-`, or `.` separators. ### License Plates (Different Formats) ```tsx function LicensePlateInput() { const plateMask = useMaskInput({ mask: [ 'AAA-9999', // Old format 'AAA9A99', // New format (Mercosul) ], }); return ( ); } ``` ### Mixed Patterns ```tsx function MixedInput() { const mixedMask = useMaskInput({ mask: '(aaa)|(999)|(9AA)', }); return ( ); } ``` Accepts: - `ABC` (three letters) - `123` (three digits) - `1AB` (digit + two letters) ### Complex Alternator ```tsx function ComplexInput() { const complexMask = useMaskInput({ mask: 'aaaa|9999|9AA9', }); return ( ); } ``` ## Tips - Use alternator masks when you need to support multiple input formats - Arrays are cleaner for complex alternators with many options - The mask automatically detects which pattern matches the input - Alternator masks are perfect for phone numbers, dates, and IDs with multiple formats --- # Preprocessing Mask Preprocessing masks allow you to define the mask as a function that can dynamically determine the mask pattern. This is useful when you need to sort multiple masks, retrieve mask definitions dynamically, or apply conditional logic based on the input. ## Basic Syntax Pass a function that returns a valid mask definition: ```tsx import { useMaskInput } from 'use-mask-input'; function DynamicInput() { const mask = useMaskInput({ mask: function() { // Your logic here return ['[1-]AAA-999', '[1-]999-AAA']; }, }); return ( ); } ``` ## Common Examples ### Conditional Mask Based on Input Length ```tsx function ConditionalInput() { const mask = useMaskInput({ mask: function() { // Return different masks based on some condition const isLongFormat = true; // Your condition logic if (isLongFormat) { return '9999-9999-9999-9999'; } return '9999-9999'; }, }); return ( ); } ``` ### Sorted Multiple Masks ```tsx function SortedMasksInput() { const mask = useMaskInput({ mask: function() { // Sort masks by priority or complexity return [ '9999-9999', // Simple format first '99999-9999', // Medium format '(99) 99999-9999', // Complex format last ]; }, }); return ( ); } ``` ### Dynamic Mask from API ```tsx function ApiBasedInput() { const [maskPattern, setMaskPattern] = useState('9999-9999'); useEffect(() => { // Fetch mask pattern from API fetch('/api/mask-pattern') .then(res => res.json()) .then(data => setMaskPattern(data.pattern)); }, []); const mask = useMaskInput({ mask: function() { return maskPattern; }, }); return ( ); } ``` ### Country-Based Phone Mask ```tsx function CountryPhoneInput({ country }: { country: string }) { const mask = useMaskInput({ mask: function() { const countryMasks: Record = { 'US': '(999) 999-9999', 'BR': '(99) 99999-9999', 'UK': '9999 999 999', 'DE': '9999 9999999', }; return countryMasks[country] || '9999-9999'; }, }); return ( ); } ``` ### User Preference Based Mask ```tsx function UserPreferenceInput() { const userPreference = 'dashes'; // 'dashes' | 'spaces' | 'dots' const mask = useMaskInput({ mask: function() { switch (userPreference) { case 'dashes': return '9999-9999-9999-9999'; case 'spaces': return '9999 9999 9999 9999'; case 'dots': return '9999.9999.9999.9999'; default: return '9999999999999999'; } }, }); return ( ); } ``` ### Complex Conditional Logic ```tsx function ComplexConditionalInput() { const inputType = 'phone'; // 'phone' | 'email' | 'postal' const mask = useMaskInput({ mask: function() { if (inputType === 'phone') { return ['(99) 9999-9999', '(99) 99999-9999']; } if (inputType === 'email') { return '*{1,20}[.*{1,20}][.*{1,20}][.*{1,20}]@*{1,20}[.*{2,6}][.*{1,2}]'; } if (inputType === 'postal') { return '99999-9999'; } return '9999-9999'; }, }); return ( ); } ``` ## Tips - Use preprocessing masks when you need dynamic mask selection - Perfect for country-specific formats or user preferences - Can be combined with state management for reactive mask changes - Useful when mask patterns need to be fetched from an API - The function is called when the mask needs to be evaluated --- # Ant Design Integration **use-mask-input** provides dedicated hooks for seamless integration with Ant Design components. These hooks handle Ant Design's `InputRef` structure automatically, making it easy to add masks to your Ant Design forms. ## Installation Make sure you have both `use-mask-input` and `antd` installed: ```bash npm install use-mask-input antd ``` ## useMaskInputAntd The `useMaskInputAntd` hook is specifically designed for Ant Design's `Input` component. It handles the `InputRef` structure automatically. ### Basic Usage ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function PhoneInput() { const maskRef = useMaskInputAntd({ mask: 'phone', }); return ( ); } ``` ### With Options ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function EmailInput() { const maskRef = useMaskInputAntd({ mask: 'email', }); return ( ); } ``` ### With Register Callback You can also use a register callback to integrate with form libraries: ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function FormInput() { const maskRef = useMaskInputAntd({ mask: '9999-9999', register: (element) => { // Do something with the element console.log('Input element:', element); }, }); return ( ); } ``` ### With Ant Design Form (Form.Item + name) `useMaskInputAntd` works with Ant Design's native `Form` component. Use `Form.Item` with `name` to let the form manage value and validation automatically: ```tsx import { Button, Form, Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function AntdFormExample() { const [form] = Form.useForm(); const phoneMaskRef = useMaskInputAntd({ mask: '(999) 999-9999', }); const emailMaskRef = useMaskInputAntd({ mask: 'email', }); const currencyMaskRef = useMaskInputAntd({ mask: 'currency', options: { prefix: '$ ', radixPoint: '.', digits: 2, groupSeparator: ',', rightAlign: false, }, }); const onFinish = (values: Record) => { console.log('Form values:', values); }; return (
); } ``` #### Watching form values Use `Form.useWatch` to observe masked values in real time: ```tsx import { Form, Input, Typography } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function WatchExample() { const [form] = Form.useForm(); const values = Form.useWatch([], form); const maskRef = useMaskInputAntd({ mask: 'email' }); return (
Current value: {values?.email}
); } ``` #### Submitting and accessing values Call `form.getFieldsValue()` or use the `onFinish` callback to get the form values. The values reflect what Inputmask writes to the DOM (masked by default, or unmasked if `autoUnmask: true` is set in options). ## useHookFormMaskAntd The `useHookFormMaskAntd` hook combines React Hook Form with Ant Design, providing a seamless way to register masked inputs. ### Basic Usage with React Hook Form ```tsx import { Input } from 'antd'; import { useForm } from 'react-hook-form'; import { useHookFormMaskAntd } from 'use-mask-input/antd'; interface FormData { phone: string; email: string; } function MyForm() { const { register, handleSubmit } = useForm(); const registerWithMask = useHookFormMaskAntd(register); const onSubmit = (data: FormData) => { console.log(data); }; return (
); } ``` ### With Validation You can combine masks with React Hook Form validation: ```tsx import { Input } from 'antd'; import { useForm } from 'react-hook-form'; import { useHookFormMaskAntd } from 'use-mask-input/antd'; interface FormData { phone: string; email: string; } function ValidatedForm() { const { register, handleSubmit, formState: { errors } } = useForm(); const registerWithMask = useHookFormMaskAntd(register); const onSubmit = (data: FormData) => { console.log(data); }; return (
{errors.phone && {errors.phone.message}}
{errors.email && {errors.email.message}}
); } ``` ### With Ant Design Form You can also use it with Ant Design's Form component: ```tsx import { Form, Input, Button } from 'antd'; import { useForm } from 'react-hook-form'; import { useHookFormMaskAntd } from 'use-mask-input/antd'; function AntdForm() { const { register, handleSubmit } = useForm(); const registerWithMask = useHookFormMaskAntd(register); const onSubmit = (data: any) => { console.log(data); }; return (
); } ``` ## API Reference For full API documentation of all exports (including standard hooks, higher-order functions, and types), see the **[API Reference](./api-reference)** page. Below is a quick reference for the Ant Design-specific hooks. ### useMaskInputAntd ```tsx function useMaskInputAntd(props: { mask: Mask; register?: (element: HTMLElement) => void; options?: Options; }): (input: InputRef | null) => void ``` | Parameter | Type | Required | Description | |-----------|------|:--------:|-------------| | `mask` | `Mask` | Yes | The mask pattern, alias, or array of patterns. | | `register` | `(element: HTMLElement) => void` | No | Callback that receives the resolved DOM element. | | `options` | `Options` | No | Inputmask configuration options (placeholder, autoUnmask, etc.). | **Returns** a stable ref callback that accepts Ant Design's `InputRef` and applies the mask to the underlying input element. Uses `useCallback` internally, so no need for `React.memo`. ### useHookFormMaskAntd ```tsx function useHookFormMaskAntd( registerFn: UseFormRegister ): ( fieldName: Path, mask: Mask, options?: RegisterOptions & Options ) => UseHookFormMaskAntdReturn ``` | Parameter | Type | Required | Description | |-----------|------|:--------:|-------------| | `registerFn` | `UseFormRegister` | Yes | The `register` function returned by `useForm()`. | **Returns** a function with the signature `(fieldName, mask, options?)` that returns an object you spread onto Ant Design's `Input`. Uses `useMemo` internally, so no need for `React.memo`. ## Differences from Standard Hooks The Ant Design hooks differ from the standard hooks in the following ways: 1. **InputRef Handling**: Automatically unwraps Ant Design's `InputRef` structure (which wraps the actual `` element) before applying the mask 2. **Type Safety**: Ref callbacks accept `InputRef | null` instead of `HTMLElement | null`, so TypeScript works out of the box with `` 3. **Same Stability Guarantees**: Both Ant Design hooks use `useCallback` / `useMemo` internally, just like their standard counterparts. No `React.memo` needed ## Examples ### Phone Number Input ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function PhoneInput() { const maskRef = useMaskInputAntd({ mask: 'phone' }); return ; } ``` ### Email input ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function EmailInput() { const maskRef = useMaskInputAntd({ mask: 'email' }); return ; } ``` ### Credit Card Input ```tsx import { Input } from 'antd'; import { useMaskInputAntd } from 'use-mask-input/antd'; function CreditCardInput() { const maskRef = useMaskInputAntd({ mask: '9999 9999 9999 9999', }); return ; } ``` ## Next Steps - Explore [mask types](./tutorial-basics/static-mask) - Check out [all available aliases](./tutorial-basics/alias-mask) - Learn about [optional masks](./tutorial-basics/optional-mask) - Discover [dynamic masks](./tutorial-basics/dynamic-mask) --- # TanStack Form Integration `use-mask-input` supports TanStack Form through two APIs: - `useTanStackFormMask` (hook, recommended) - `withTanStackFormMask` (function, requires `React.memo`) ## Installation ```bash npm install use-mask-input @tanstack/react-form ``` ## useTanStackFormMask `useTanStackFormMask` returns a helper that receives your TanStack input props and returns masked input props with a stable ref callback. ### Basic usage ```tsx import { useForm } from '@tanstack/react-form'; import { useTanStackFormMask } from 'use-mask-input'; type FormValues = { phone: string; }; function MyForm() { const maskField = useTanStackFormMask(); const form = useForm({ defaultValues: { phone: '' } as FormValues, onSubmit: async ({ value }) => { console.log(value); }, }); return (
{ event.preventDefault(); event.stopPropagation(); void form.handleSubmit(); }} > {(field) => { const inputProps = maskField( '(99) 99999-9999', { name: field.name, value: field.state.value, onBlur: field.handleBlur, onChange: (event) => field.handleChange(event.target.value), }, ); return ; }}
); } ``` ### With custom options ```tsx const inputProps = maskField( 'currency', { name: field.name, value: field.state.value, onBlur: field.handleBlur, onChange: (event) => field.handleChange(event.target.value), }, { prefix: '$ ', groupSeparator: ',', digits: 2, rightAlign: false, }, ); ``` ## withTanStackFormMask `withTanStackFormMask` is the function version. Use it when the input props object is already available and you want to apply the mask at that point. Because this is not a hook, make sure the component is memoized when needed. ```tsx import { memo } from 'react'; import { withTanStackFormMask } from 'use-mask-input'; const MaskedField = memo(function MaskedField({ inputProps, }: { inputProps: { name: string; value: string; onBlur: () => void; onChange: (event: React.ChangeEvent) => void; }; }) { const maskedProps = withTanStackFormMask(inputProps, '(99) 99999-9999'); return ; }); ``` ## API signatures ```ts function useTanStackFormMask(): ( mask: Mask, inputProps: T, options?: Options ) => UseTanStackFormMaskReturn ``` ```ts function withTanStackFormMask( inputProps: T, mask: Mask, options?: Options ): UseTanStackFormMaskReturn ``` ## Tips - Prefer `useTanStackFormMask` for regular component usage. - Keep passing `name`, `value`, `onBlur`, and `onChange` from `field`. - Use alias masks like `email`, `currency`, `datetime`, and custom patterns like `(99) 99999-9999`.