1 import { useEffect, useRef, useState } from 'react';
3 import type { FieldProps } from 'formik';
4 import type { InputMask, InputMaskElement } from 'imask';
5 import IMask from 'imask/esm/imask';
6 import type { FactoryOpts } from 'imask/masked/factory';
8 import type { MaybeNull } from '@proton/pass/types';
9 import noop from '@proton/utils/noop';
11 export const useFieldMask = <Opts extends FactoryOpts>({ form, field }: FieldProps, options: Opts) => {
12 const { value, name } = field;
13 const [maskedValue, setMaskedValue] = useState<string>('');
14 const maskRef = useRef<MaybeNull<InputMask<Opts>>>();
15 const inputRef = useRef<InputMaskElement>();
18 if (inputRef.current) {
19 maskRef.current = maskRef.current ?? IMask<Opts>(inputRef.current, options);
20 maskRef.current.updateOptions(options as any);
25 if (maskRef.current) {
26 maskRef.current.on('accept', () => {
27 setMaskedValue(maskRef.current!.value);
28 form.setFieldValue(name, maskRef.current!.unmaskedValue).catch(noop);
34 /* if the current unmasked value doesn't match our field's value
35 * then we have programatically set the field's value. In this case
36 * we need to reconciliate imask with the new values */
37 if (maskRef.current && value !== maskRef.current?.unmaskedValue) {
38 maskRef.current.typedValue = value;
39 maskRef.current.unmaskedValue = value;
40 maskRef.current.updateValue();
41 setMaskedValue(maskRef.current.value);
45 useEffect(() => () => maskRef.current?.destroy(), []);
47 return { inputRef, maskedValue };