useMask

useMask (입력 마스킹)

useMask 훅은 전화번호, 신용카드 번호, 날짜 같은 입력을 마스킹해요. 빌트인 토큰과 커스텀 토큰, 동적 마스크, 정규식 배열 형식을 지원해요.

출처: 문서

본문

useMask 훅을 사용해 입력 필드에 마스킹을 적용할 수 있어요. 반환값의 ref를 입력 요소에 전달하고, value와 rawValue로 표시 값과 원시 값을 각각 읽을 수 있어요.

import { TextInput, Text } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, value, rawValue } = useMask({ mask: '(999) 999-9999' });

  return (
    <>
      <TextInput label="Phone number" ref={ref} />
      <Text>Masked value: {value}</Text>
      <Text>Raw value: {rawValue}</Text>
    </>
  );
}

isComplete, slotChar 그리고 transform

isComplete로 필요한 마스크 슬롯이 모두 채워졌는지 확인할 수 있어요. 예를 들어 제출 버튼을 제어할 때 사용해요. slotChar 옵션은 각 슬롯의 위치 힌트를 보여주는 여러 문자로 된 문자열을 받아요. transform 옵션은 검증 전에 각 문자를 변환해요. 다음 예시에서는 입력을 자동으로 대문자로 만들므로 A 토큰([A-Z])이 소문자도 받아들여요.

import { Button, Group, Text, TextInput } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, isComplete, rawValue } = useMask({
    mask: 'AAA-9999',
    slotChar: 'XXX-0000',
    transform: (char) => char.toUpperCase(),
  });

  return (
    <>
      <TextInput label="Promo code" ref={ref} />
      <Text>Raw value: {rawValue}</Text>
      <Button disabled={!isComplete}>Apply code</Button>
    </>
  );
}

동적 마스크 (Dynamic mask)

modify 옵션으로 현재 입력 값에 따라 마스크를 변경할 수 있어요. 이 예시는 표준 신용카드 형식과 American Express 형식을 전환해요.

import { TextInput, Text } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, rawValue } = useMask({
    mask: '9999 9999 9999 9999',
    modify: (value) => {
      const digits = value.replace(/\D/g, '');
      if (digits.startsWith('34') || digits.startsWith('37')) {
        return { mask: '9999 999999 99999' };
      }
    },
  });

  return (
    <>
      <TextInput label="Credit card number" ref={ref} />
      <Text>Raw value: {rawValue}</Text>
      <Text>Try starting with 34 or 37 for Amex format</Text>
    </>
  );
}

커스텀 토큰 (Custom tokens)

tokens 옵션으로 빌트인 토큰 맵을 재정의하거나 확장할 수 있어요.

import { TextInput, Text } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, rawValue } = useMask({
    mask: '\\#hhhhhh',
    tokens: { h: /[0-9a-fA-F]/ },
  });

  return (
    <>
      <TextInput label="Hex color" ref={ref} />
      <Text>Raw value: {rawValue}</Text>
    </>
  );
}

이스케이프 (Escaping)

토큰 문자 앞에 \를 붙여 리터럴로 처리할 수 있어요. 이 예시에서 A는 보통 대문자 토큰이지만 \A는 리터럴 문자가 돼요.

import { TextInput, Text } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, rawValue } = useMask({
    mask: '\\A-9999',
  });

  return (
    <>
      <TextInput label="Product code" ref={ref} />
      <Text>Raw value: {rawValue}</Text>
    </>
  );
}

정규식 배열 형식 (Regex array format)

빌트인 토큰으로 충분하지 않은 복잡한 마스크에는 문자열 리터럴과 RegExp 객체의 배열을 전달해요. 이 예시는 첫 번째 자릿수를 0-2로, 분의 십의 자리를 0-5로 제한하는 시간 입력을 만들어요.

import { TextInput, Text } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, rawValue } = useMask({
    mask: [/[0-2]/, /\d/, ':', /[0-5]/, /\d/],
  });

  return (
    <>
      <TextInput label="Time (HH:MM)" ref={ref} />
      <Text>Raw value: {rawValue}</Text>
    </>
  );
}

초기화 (Reset)

훅이 반환하는 reset 함수를 사용해 입력 값을 프로그래밍 방식으로 지울 수 있어요.

import { Button, Group, Text, TextInput } from '@mantine/core';
import { useMask } from '@mantine/hooks';

function Demo() {
  const { ref, value, rawValue, reset } = useMask({
    mask: '(999) 999-9999',
  });

  return (
    <>
      <TextInput label="Phone number" ref={ref} />
      <Text>Masked: {value}</Text>
      <Text>Raw: {rawValue}</Text>
      <Button onClick={reset}>Reset</Button>
    </>
  );
}

마스크 패턴 문법 (Mask pattern syntax)

마스크 문자열은 기대하는 형식을 정의해요. 각 문자는 토큰(편집 가능한 슬롯) 또는 리터럴(자동으로 삽입되는 고정 문자)이에요.

빌트인 토큰 (Built-in tokens)

  • 9 — 숫자 한 자리 ([0-9])
  • a — 알파벳 한 자 ([A-Za-z])
  • A — 대문자 한 자 ([A-Z])
  • * — 영숫자 한 자 ([A-Za-z0-9])
  • # — 숫자 또는 부호 ([-+0-9])

선택적 세그먼트 (Optional segments)

마지막 필수 문자 뒤에 ?를 붙이면 나머지 슬롯을 선택적으로 표시해요.

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

유틸리티 함수 (Utility functions)

다음 순수 함수들이 훅과 함께 내보내져요.

  • formatMask(raw, options) — 원시 값 문자열에 마스크 적용
  • unformatMask(masked, options) — 마스킹된 값에서 모든 마스크 리터럴 제거
  • isMaskComplete(masked, options) — 모든 필수 슬롯이 채워졌는지 확인
  • generatePattern(mode, options) — HTML pattern 속성용 정규식 문자열 생성
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)

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;
  // 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

UseMaskOptions와 UseMaskReturnValue 타입은 @mantine/hooks 패키지에서 내보내져요.

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

더 알아보기 (Learn more)