import React, { ChangeEvent, FormEvent, KeyboardEvent, ReactElement, ReactNode, useEffect, useState } from 'react' import InputElement from './InputElement' import Label from './Label' import styles from './index.module.css' import { ErrorMessage, FieldInputProps } from 'formik' import classNames from 'classnames/bind' import Disclaimer from './Disclaimer' import Tooltip from '@shared/atoms/Tooltip' import Markdown from '@shared/Markdown' import FormHelp from './Help' const cx = classNames.bind(styles) export interface InputProps { name: string label?: string | ReactNode placeholder?: string required?: boolean help?: string prominentHelp?: boolean tag?: string type?: string options?: string[] sortOptions?: boolean additionalComponent?: ReactElement value?: string | number onChange?( e: | FormEvent | ChangeEvent | ChangeEvent | ChangeEvent ): void onKeyPress?( e: | KeyboardEvent | KeyboardEvent | KeyboardEvent | KeyboardEvent ): void rows?: number multiple?: boolean pattern?: string min?: string max?: string disabled?: boolean readOnly?: boolean field?: FieldInputProps form?: any prefix?: string | ReactElement postfix?: string | ReactElement step?: string defaultChecked?: boolean size?: 'mini' | 'small' | 'large' | 'default' className?: string checked?: boolean disclaimer?: string disclaimerValues?: string[] } export default function Input(props: Partial): ReactElement { const { label, help, prominentHelp, additionalComponent, size, form, field, disclaimer, disclaimerValues } = props const isFormikField = typeof field !== 'undefined' const isNestedField = field?.name?.includes('.') // TODO: this feels hacky as it assumes nested `values` store. But we can't use the // `useField()` hook in here to get `meta.error` so we have to match against form?.errors? // handling flat and nested data at same time. const parsedFieldName = isFormikField && (isNestedField ? field?.name.split('.') : [field?.name]) // const hasFormikError = !!meta?.touched && !!meta?.error const hasFormikError = form?.errors !== {} && form?.touched?.[parsedFieldName[0]]?.[parsedFieldName[1]] && form?.errors?.[parsedFieldName[0]]?.[parsedFieldName[1]] const styleClasses = cx({ field: true, hasError: hasFormikError }) const [disclaimerVisible, setDisclaimerVisible] = useState(true) useEffect(() => { if (!isFormikField) return if (disclaimer && disclaimerValues) { setDisclaimerVisible( disclaimerValues.includes( props.form?.values[parsedFieldName[0]]?.[parsedFieldName[1]] ) ) } }, [isFormikField, props.form?.values]) return (
{help && prominentHelp && {help}} {isFormikField && hasFormikError && (
)} {disclaimer && ( {disclaimer} )} {additionalComponent && additionalComponent}
) }