input component

mail@pastecode.io avatar
unknown
javascript
a year ago
2.3 kB
2
Indexable
Never
import { ChangeEventHandler, useState } from 'react';
import { Controller } from 'react-hook-form';
import { Typography } from 'antd';
import { get } from 'lodash';
import * as Styled from './styled';
import type { FunctionComponent } from 'react';
import type {
  Control,
  FieldValues,
  ControllerRenderProps,
  ControllerFieldState,
} from 'react-hook-form';

const { Text } = Typography;

/* eslint-disable max-lines-per-function */
const Input: FunctionComponent<{
  name: string;
  controlType: 'normal' | 'controlled';
  size?: 'small' | 'medium' | 'large';
  placeholder?: string;
  disabled?: boolean;
  useVisibilityToggle?: boolean;
  control?: Control<FieldValues, App.Any>;
  value?: string;
  onChange?: ChangeEventHandler<HTMLInputElement>;
}> = ({
  name,
  controlType,
  size = 'medium',
  useVisibilityToggle = true,
  placeholder,
  disabled,
  control,
}) => {
  const [inputValueVisible, setInputValueVisible] = useState<boolean>(true);

  const getIconRenderProps = (useVisibilityToggle: boolean) => {
    const props: {
      iconRender?: (visible: boolean) => React.ReactNode;
    } = {};

    if (!useVisibilityToggle) {
      props.iconRender = (_) => null;
    }
    return props;
  };

  const renderInputField = (
    fieldProps?: ControllerRenderProps<FieldValues, string>,
    fieldState?: ControllerFieldState,
  ) => (
    <Styled.Input
      size={size === 'medium' ? 'middle' : size}
      status={!!get(fieldState, 'error') && 'error'}
      disabled={disabled}
      placeholder={placeholder}
      visibilityToggle={{
        visible: inputValueVisible,
        onVisibleChange: setInputValueVisible,
      }}
      {...fieldProps}
      {...getIconRenderProps(useVisibilityToggle)}
    />
  );

  const renderComponent = (): JSX.Element => {
    if (controlType === 'normal') {
      return renderInputField();
    }

    return (
      <Controller
        name={name}
        control={control}
        render={({ field, fieldState }) => (
          <>
            {renderInputField(field, fieldState)}
            {!!get(fieldState, 'error') && (
              <Text type="danger">{!!get(fieldState, 'error.message')}</Text>
            )}
          </>
        )}
      />
    );
  };

  return <>{renderComponent()}</>;
};
/* eslint-disable max-lines-per-function */

export default Input;