forked from mirrors/thatmattlove-hyperglass
67 lines
2 KiB
TypeScript
67 lines
2 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { Flex, FormControl, FormLabel, FormErrorMessage } from '@chakra-ui/react';
|
|
import { useFormContext } from 'react-hook-form';
|
|
import { If, Then } from 'react-if';
|
|
import { useColorValue } from '~/context';
|
|
import { useBooleanValue } from '~/hooks';
|
|
|
|
import type { FieldError } from 'react-hook-form';
|
|
import type { FormData } from '~/types';
|
|
import type { TField } from './types';
|
|
|
|
export const FormField = (props: TField): JSX.Element => {
|
|
const { name, label, children, labelAddOn, fieldAddOn, hiddenLabels = false, ...rest } = props;
|
|
const labelColor = useColorValue('blackAlpha.700', 'whiteAlpha.700');
|
|
const errorColor = useColorValue('red.500', 'red.300');
|
|
const opacity = useBooleanValue(hiddenLabels, 0, undefined);
|
|
|
|
const { formState } = useFormContext<FormData>();
|
|
|
|
const error = useMemo<FieldError | null>(() => {
|
|
if (name in formState.errors) {
|
|
console.group(`Error on field '${label}'`);
|
|
console.warn(formState.errors[name as keyof FormData]);
|
|
console.groupEnd();
|
|
return formState.errors[name as keyof FormData] as FieldError;
|
|
}
|
|
return null;
|
|
}, [formState, label, name]);
|
|
|
|
return (
|
|
<FormControl
|
|
mx={2}
|
|
w="100%"
|
|
maxW="100%"
|
|
flexDir="column"
|
|
my={{ base: 2, lg: 4 }}
|
|
isInvalid={error !== null}
|
|
{...rest}
|
|
>
|
|
<FormLabel
|
|
pr={0}
|
|
mb={{ lg: 4 }}
|
|
htmlFor={name}
|
|
display="flex"
|
|
opacity={opacity}
|
|
fontWeight="bold"
|
|
alignItems="center"
|
|
justifyContent="space-between"
|
|
color={error !== null ? errorColor : labelColor}
|
|
>
|
|
{label}
|
|
<If condition={typeof labelAddOn !== 'undefined'}>
|
|
<Then>{labelAddOn}</Then>
|
|
</If>
|
|
</FormLabel>
|
|
{children}
|
|
<If condition={typeof fieldAddOn !== 'undefined'}>
|
|
<Then>
|
|
<Flex justify="flex-end" pt={3}>
|
|
{fieldAddOn}
|
|
</Flex>
|
|
</Then>
|
|
</If>
|
|
<FormErrorMessage opacity={opacity}>{error?.message}</FormErrorMessage>
|
|
</FormControl>
|
|
);
|
|
};
|