Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / pass / components / Form / Field / TextField.tsx
blob734144c5a2e9a160c89df2ca840d97d83f968ddf
1 import type { ForwardRefRenderFunction } from 'react';
2 import { forwardRef, useState } from 'react';
4 import { type FieldProps } from 'formik';
6 import type { Input } from '@proton/atoms';
7 import { InputFieldTwo } from '@proton/components';
8 import { type InputFieldProps } from '@proton/components/components/v2/field/InputField';
9 import { pipe } from '@proton/pass/utils/fp/pipe';
10 import { isEmptyString } from '@proton/pass/utils/string/is-empty-string';
11 import clsx from '@proton/utils/clsx';
12 import identity from '@proton/utils/identity';
14 import { useFieldControl } from '../../../hooks/useFieldControl';
15 import { useMaxLengthLimiter } from '../../../hooks/useMaxLengthLimiter';
16 import { usePasteLengthLimiter } from '../../../hooks/usePasteLengthLimiter';
17 import { FieldBox, type FieldBoxProps } from './Layout/FieldBox';
19 export type BaseTextFieldProps = FieldProps &
20     InputFieldProps<typeof Input> & {
21         hidden?: boolean;
22         hiddenValue?: string;
23         lengthLimiters?: boolean;
24     };
26 const BaseTextFieldRender: ForwardRefRenderFunction<HTMLInputElement, BaseTextFieldProps> = (
27     {
28         field,
29         form,
30         meta,
31         hidden = false,
32         hiddenValue,
33         inputClassName,
34         labelContainerClassName,
35         lengthLimiters = false,
36         onKeyDown,
37         onFocus = identity,
38         onPaste,
39         ...props
40     },
41     ref
42 ) => {
43     const { onBlur, value } = field;
44     const { error } = useFieldControl({ field, form, meta });
45     const [focused, setFocused] = useState<boolean>(false);
46     const hide = hidden && !isEmptyString(value) && !focused;
47     const pasteLengthLimiter = usePasteLengthLimiter();
48     const maxLengthLimiter = useMaxLengthLimiter();
49     const defaultHiddenValue = '••••••••••••';
51     return (
52         <InputFieldTwo
53             unstyled
54             assistContainerClassName="empty:hidden"
55             error={error}
56             inputClassName={clsx('p-0 rounded-none', props.disabled ? 'color-disabled' : 'color-norm', inputClassName)}
57             labelContainerClassName={clsx(
58                 'm-0 text-normal text-sm',
59                 error ? 'color-danger' : 'color-weak',
60                 labelContainerClassName
61             )}
62             {...props}
63             {...field}
64             onBlur={pipe(onBlur, () => setFocused(false))}
65             onFocus={pipe(onFocus, () => setFocused(true))}
66             onKeyDown={lengthLimiters && props.maxLength ? maxLengthLimiter(props.maxLength, onKeyDown) : onKeyDown}
67             onPaste={lengthLimiters && props.maxLength ? pasteLengthLimiter(props.maxLength, onPaste) : onPaste}
68             ref={ref}
69             type="text"
70             value={hide ? (hiddenValue ?? defaultHiddenValue) : value}
71         />
72     );
75 export const BaseTextField = forwardRef(BaseTextFieldRender);
77 export type TextFieldProps = FieldBoxProps & BaseTextFieldProps;
79 export const TextFieldRender: ForwardRefRenderFunction<HTMLInputElement, TextFieldProps> = (
80     { actions, actionsContainerClassName, className, icon, ...rest },
81     ref
82 ) => {
83     return (
84         <FieldBox
85             actions={actions}
86             actionsContainerClassName={actionsContainerClassName}
87             className={className}
88             icon={icon}
89         >
90             <BaseTextField {...rest} ref={ref} />
91         </FieldBox>
92     );
95 export const TextField = forwardRef(TextFieldRender);