Back to Mantine

Use Mask

apps/mantine.dev/src/pages/hooks/use-mask.mdx

9.5.25.0 KB
Original Source

import { UseMaskDemos } from '@docs/demos'; import { Layout } from '@/layout'; import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.useMask);

Usage

useMask attaches real-time input masking to any <input> element via a ref callback. It formats user input against a defined pattern and exposes both the masked display value and the raw unmasked value. If you need a ready-made input component, use MaskInput which wraps this hook with all standard input props.

<Demo data={UseMaskDemos.usage} />

isComplete, slotChar, and transform

Use isComplete to check whether all required mask slots are filled — for example, to control a submit button. The slotChar option accepts a multi-character string to show positional hints for each slot. The transform option converts each character before validation — this example uses it to auto-uppercase input so the A token ([A-Z]) accepts lowercase letters:

<Demo data={UseMaskDemos.complete} />

Dynamic mask

Use the modify option to change the mask based on the current input value. This example switches between standard and American Express credit card formats:

<Demo data={UseMaskDemos.dynamic} />

Custom tokens

Override or extend the built-in token map with the tokens option:

<Demo data={UseMaskDemos.customTokens} />

Escaping

Prefix a token character with \ to treat it as a literal. In this example, A would normally be an uppercase letter token, but \A makes it a literal character:

<Demo data={UseMaskDemos.escape} />

Regex array format

For complex masks where built-in tokens are not enough, pass an array of string literals and RegExp objects. This example creates a time input where the first digit is restricted to 0-2 and the minute tens digit to 0-5:

<Demo data={UseMaskDemos.regex} />

Reset

Use the reset function returned by the hook to programmatically clear the input value:

<Demo data={UseMaskDemos.reset} />

Mask pattern syntax

The mask string defines the expected format. Each character is either a token (editable slot) or a literal (fixed character inserted automatically).

Built-in tokens

  • 9 – any single digit ([0-9])
  • a – any single letter ([A-Za-z])
  • A – any uppercase letter ([A-Z])
  • * – any alphanumeric character ([A-Za-z0-9])
  • # – digit or sign ([-+0-9])

Optional segments

Append ? after the last required character to mark remaining slots as optional:

tsx
useMask({ mask: '(999) 999-9999? x9999' }) // Extension is optional

Utility functions

The following pure functions are exported alongside the hook:

  • formatMask(raw, options) – apply a mask to a raw value string
  • unformatMask(masked, options) – strip all mask literals from a masked value
  • isMaskComplete(masked, options) – check if all required slots are filled
  • generatePattern(mode, options) – generate a regex string for HTML pattern attribute
tsx
import { formatMask, unformatMask, isMaskComplete } from '@mantine/hooks';

const options = { mask: '(999) 999-9999' };

formatMask('1234567890', options);      // "(123) 456-7890"
unformatMask('(123) 456-7890', options); // "1234567890"
isMaskComplete('(123) 456-7890', options); // true

Definition

tsx
interface UseMaskOptions {
  // Mask pattern string or array of string literals and RegExp objects
  mask: string | Array<string | RegExp>;

  // Override or extend the default token map
  tokens?: Record<string, RegExp>;

  // Called on each keystroke, can return overrides for mask, tokens, or slotChar
  modify?: (value: string) => Partial<Pick<UseMaskOptions, 'mask' | 'tokens' | 'slotChar'>> | undefined;

  // Transform each character before validation and insertion
  transform?: (char: string) => string;

  // Character displayed in unfilled slots, "_" by default
  slotChar?: string | null;

  // Show mask pattern even when the field is empty and unfocused
  alwaysShowMask?: boolean;

  // Show mask placeholder on focus, true by default
  showMaskOnFocus?: boolean;

  // Clear value on blur when mask is incomplete, false by default
  autoClear?: boolean;

  // Sets aria-invalid on the input
  invalid?: boolean;

  // Called on every change with raw and masked values
  onChangeRaw?: (rawValue: string, maskedValue: string) => void;

  // Called when all required mask slots are filled
  onComplete?: (maskedValue: string, rawValue: string) => void;

}

interface UseMaskReturnValue {
  // Ref callback to attach to the input element
  ref: React.RefCallback<HTMLInputElement>;

  // Current masked display value
  value: string;

  // Current raw unmasked value
  rawValue: string;

  // Whether all required mask slots are filled
  isComplete: boolean;

  // Clear the input value and reset state
  reset: () => void;
}

function useMask(options: UseMaskOptions): UseMaskReturnValue;

Exported types

The UseMaskOptions and UseMaskReturnValue types are exported from the @mantine/hooks package; you can import them in your application:

tsx
import type { UseMaskOptions, UseMaskReturnValue } from '@mantine/hooks';