Form

This component provides Form functionality.

Props

  • prop1: Description of prop1.
  • prop2: Description of prop2.

Usage

import { Form } from './Form';

const props = {};

<Form prop1="value1" prop2="value2" />;
import { zodResolver } from '@hookform/resolvers/zod';
import type { ComponentProps, FC } from 'react';
import type {
  FieldValues,
  Resolver,
  SubmitHandler,
  UseFormProps,
  UseFormReturn
} from 'react-hook-form';
import { FormProvider, useForm, useFormContext } from 'react-hook-form';
import type { TypeOf, ZodSchema } from 'zod';

import cn from '../cn';

interface UseZodFormProps<T extends ZodSchema<FieldValues>>
  extends UseFormProps<TypeOf<T>> {
  schema: T;
}

export const useZodForm = <T extends ZodSchema<FieldValues>>({
  schema,
  ...formConfig
}: UseZodFormProps<T>) => {
  return useForm({
    ...formConfig,
    resolver: zodResolver(schema) as Resolver<TypeOf<T>, any>
  });
};

interface FieldErrorProps {
  name?: string;
}

export const FieldError: FC<FieldErrorProps> = ({ name }) => {
  const {
    formState: { errors }
  } = useFormContext();

  if (!name) {
    return null;
  }

  const error = errors[name];

  if (!error) {
    return null;
  }

  return (
    <div className="mt-1 text-sm font-bold text-red-500">
      {error.message as string}
    </div>
  );
};

interface FormProps<T extends FieldValues = Record<string, unknown>>
  extends Omit<ComponentProps<'form'>, 'onSubmit'> {
  form: UseFormReturn<T>;
  onSubmit: SubmitHandler<T>;
  className?: string;
}

export const Form = <T extends FieldValues>({
  form,
  onSubmit,
  children,
  className = ''
}: FormProps<T>) => {
  return (
    <FormProvider {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <fieldset
          className={cn('flex flex-col', className)}
          disabled={form.formState.isSubmitting}
        >
          {children}
        </fieldset>
      </form>
    </FormProvider>
  );
};