Stop fighting with input masks. 🤯
One mask engine, two frameworks. A hook for React, a directive for Vue 3, and no adapter needed for React Hook Form, TanStack Form, vee-validate, shadcn/ui or Ant Design.
$npm install use-mask-inputCopy. Paste. Mask.
A hook on React, a directive on Vue. Both drive the same engine, so a mask behaves identically on either side. No wrapper components, no custom inputs to learn.
import { useMaskInput } from 'use-mask-input';
function PhoneInput() {
const ref = useMaskInput({ mask: '(99) 99999-9999' });
return <input ref={ref} />;
}
import { useForm } from 'react-hook-form';
import { useHookFormMask } from 'use-mask-input';
function MyForm() {
const { register, handleSubmit } = useForm();
const registerWithMask = useHookFormMask(register);
return (
<form onSubmit={handleSubmit(console.log)}>
<input {...registerWithMask('phone', '(99) 99999-9999')} />
<input {...registerWithMask('email', 'email')} />
<button type="submit">Submit</button>
</form>
);
}
<script setup>
import { vMaskInput } from 'use-mask-input/vue';
</script>
<template>
<input v-mask-input="'(99) 99999-9999'" />
</template>
<script setup>
import { useField, useForm } from 'vee-validate';
import { vMaskInput } from 'use-mask-input/vue';
const cpf = { mask: 'cpf', options: { autoUnmask: true } };
const { handleSubmit } = useForm();
const { value } = useField('cpf');
// submit receives { cpf: '12345678901' }
const onSubmit = handleSubmit(console.log);
</script>
<template>
<form @submit="onSubmit">
<input v-model="value" v-mask-input="cpf" />
</form>
</template>
Built for the boring parts.
Lightweight
A thin layer over Inputmask, the only runtime dependency. Importing the Vue entry never pulls React into your bundle.
Composable
Plain refs, React Hook Form, TanStack Form, Ant Design, vee-validate, PrimeVue, Element Plus. Pick any.
Typed
First-class TypeScript on both entries. Mask presets, options, refs and directive bindings all inferred.
Accessible
Native input under the hood — screen readers, autofill, validation just work.
This spot is empty.
use-mask-input is maintained on nights and weekends. If it saves your team time, consider sponsoring — your logo lives right here, and you help keep the project alive.