MaskInput
MaskInput
마스크 패턴을 적용해 형식화된 텍스트를 입력하는 인풋 컴포넌트예요. MaskInput은 useMask 훅의 래퍼로, 표준 인풋 prop(label, description, error 등)을 모두 제공하고 모든 마스크 옵션을 지원해요. 마스크 문자열은 토큰 문자를 사용해 기대 형식을 정의해요 (9는 숫자, a는 문자 등).
출처: 문서
본문
사용법 (Usage)
MaskInput은 useMask 훅을 감싸는 래퍼로, 표준 인풋 prop(label, description, error 등)을 모두 제공하고 모든 마스크 옵션을 지원해요. 마스크 문자열은 토큰 문자를 사용해 기대 형식을 정의해요 (9는 숫자, a는 문자 등).
import { MaskInput } from '@mantine/core';
function Demo() {
return <MaskInput mask="999 999 9999" label="Phone number" />;
}
variant, size, radius, label, description, error 등의 표준 인풋 prop을 지원해요.
동적 마스크 (Dynamic mask)
modify 옵션을 사용하면 현재 입력 값에 따라 마스크를 변경할 수 있어요. 아래 예시는 일반 신용카드와 American Express 형식을 전환해요.
import { MaskInput } from '@mantine/core';
function Demo() {
return (
<MaskInput
mask="9999 9999 9999 9999"
modify={(value) => {
if (/^3[47]/.test(value)) {
return { mask: '9999 999999 99999' };
}
return undefined;
}}
/>
);
}
커스텀 토큰 (Custom tokens)
tokens 옵션으로 내장 토큰 맵을 재정의하거나 확장할 수 있어요.
import { MaskInput } from '@mantine/core';
function Demo() {
return (
<MaskInput
mask="#HHHHHH"
tokens={{ H: /[0-9a-fA-F]/ }}
label="Hex color"
/>
);
}
정규식 배열 형식 (Regex array format)
내장 토큰으로 부족한 복잡한 마스크에는 문자열 리터럴과 RegExp 객체의 배열을 전달할 수 있어요.
import { MaskInput } from '@mantine/core';
function Demo() {
return (
<MaskInput
mask={[/[0-2]/, /\d/, ':', /[0-5]/, /\d/]}
label="Time (HH:MM)"
/>
);
}
변환 (Transform)
transform 옵션을 사용하면 검증 전에 각 문자를 변환할 수 있어요. 아래 예시는 입력을 자동으로 대문자로 변환해서 A 토큰이 소문자도 받아들일 수 있게 해요.
import { MaskInput, Text } from '@mantine/core';
import { formatMask, isMaskComplete } from '@mantine/hooks';
function Demo() {
return (
<>
<MaskInput
mask="AAA-0000"
transform={(char) => char.toUpperCase()}
slotChar="XXX-0000"
label="Promo code"
/>
<Text size="sm">Type lowercase letters – they will be auto-uppercased</Text>
</>
);
}
비활성 상태 (Disabled state)
import { MaskInput } from '@mantine/core';
function Demo() {
return <MaskInput mask="999 999 9999" label="Phone number" disabled />;
}
오류 상태 (Error state)
import { MaskInput } from '@mantine/core';
function Demo() {
return (
<MaskInput mask="999 999 9999" label="Phone number" error="Invalid phone number" />
);
}
성공 상태 (Success state)
import { MaskInput } from '@mantine/core';
function Demo() {
return <MaskInput mask="999 999 9999" label="Phone number" error="Looks good!" />;
}
값 초기화 (Reset value)
MaskInput은 내부적으로 비제어(uncontrolled) 방식이어서 부모에서 value를 설정해도 값이 지워지지 않아요. resetRef prop으로 입력 값을 명령적으로 지우는 함수를 얻을 수 있어요.
import { useRef } from 'react';
import { MaskInput, Button, Group } from '@mantine/core';
function Demo() {
const resetRef = useRef<() => void>(null);
return (
<>
<MaskInput mask="999 999 9999" label="Phone number" resetRef={resetRef} />
<Group justify="center" mt="md">
<Button onClick={() => resetRef.current?.()}>Reset</Button>
</Group>
</>
);
}
use-form과 함께 쓰기 (With use-form)
MaskInput은 설계상 비제어 방식이라 내부적으로 자체 DOM 값을 관리해요. use-form과 통합하려면 defaultValue로 초기 값을 전달하고 onChangeRaw 콜백으로 마스크가 벗겨진(raw) 값을 폼 상태에 기록하면 돼요. 비제어 폼 모드에서는 form.setFieldValue에 { forceUpdate: false }를 전달해서 키 입력마다 인풋이 리마운트되지 않게 해요.
import { Button, MaskInput } from '@mantine/core';
import { useForm } from '@mantine/form';
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: { phone: '' },
});
return (
<form onSubmit={form.onSubmit((values) => console.log(values))}>
<MaskInput
mask="999 999 9999"
label="Phone"
defaultValue=""
onChangeRaw={(raw) => form.setFieldValue('phone', raw, { forceUpdate: false })}
/>
<Button type="submit">Submit</Button>
</form>
);
}
마스크 패턴 문법 (Mask pattern syntax)
마스크 문자열은 기대 형식을 정의해요. 각 문자는 토큰(편집 가능한 슬롯)이거나 리터럴(자동으로 삽입되는 고정 문자)이에요.
내장 토큰 (Built-in tokens)
9– 숫자 하나 ([0-9])a– 문자 하나 ([A-Za-z])A– 대문자 하나 ([A-Z])*– 영숫자 문자 하나 ([A-Za-z0-9])#– 숫자 또는 부호 ([-+0-9])
선택 구간 (Optional segments)
마지막 필수 문자 뒤에 ?를 붙이면 나머지 슬롯을 선택 사항으로 표시할 수 있어요.
// Extension is optional
<MaskInput mask="999-9999?" />
이스케이프 (Escaping)
토큰 문자 앞에 \를 붙이면 리터럴로 취급돼요.
// "A" is literal, not a token
<MaskInput mask="\A 999" />