All files / react-app/src/components/RHF Field.tsx

100% Statements 6/6
80% Branches 8/10
100% Functions 2/2
100% Lines 6/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93                                72x               33x 33x 33x     33x                                                                               31x                                              
import { FieldValues, RegisterOptions } from "react-hook-form";
import { FieldArrayProps, RHFSlotProps, RHFTextField } from "shared-types";
import { FormField, FormLabel } from "../Inputs/form";
import { DependencyWrapper, RHFSlot, RHFTextDisplay, ruleGenerator } from "./";
 
interface FieldProps<T extends FieldValues> extends FieldArrayProps<T> {
  index: number;
  SLOT: RHFSlotProps;
}
 
// Define a type for the rules if not already defined
type CustomRegisterOptions = Omit<
  RegisterOptions<FieldValues, never>,
  "disabled" | "valueAsNumber" | "valueAsDate" | "setValueAs"
>;
 
export const Field = <TFields extends FieldValues>({
  name,
  index,
  SLOT,
  control,
  parentId,
  ...props
}: FieldProps<TFields>) => {
  const prefix = `${name}.${index}.`;
  const adjustedPrefix = parentId + prefix;
  const adjustedSlotName = prefix + SLOT.name;
 
  // Wrapped Group
  if (SLOT.rhf === "WrappedGroup") {
    return (
      <div className="w-full">
        {(SLOT.label || SLOT.styledLabel) && (
          <FormLabel className={SLOT.labelClassName}>
            <RHFTextDisplay text={(SLOT.styledLabel || SLOT.label) as RHFTextField} />
          </FormLabel>
        )}
        <div className={SLOT.props?.wrapperClassName} key={`wrappedGroup-${name}-${index}`}>
          {SLOT.fields?.map((F) => {
            return (
              <Field {...{ name, index, control, parentId, ...props }} SLOT={F} key={F.name} />
            );
          })}
        </div>
      </div>
    );
  }
 
  // Base Field
  const formField = (
    <FormField
      key={adjustedSlotName}
      // @ts-expect-error
      control={control}
      rules={ruleGenerator(SLOT.rules, SLOT.addtnlRules) as CustomRegisterOptions}
      name={adjustedSlotName as never}
      render={RHFSlot({
        ...SLOT,
        index: index,
        control: control,
        name: adjustedSlotName,
        parentId: adjustedPrefix,
      })}
    />
  );
 
  // If the slot has a dependency, wrap it in a dependency wrapper.
  // Ensure the conditions are adjusted to the new name within the FieldGroup.
  // Otherwise, just return the form field:
  return SLOT.dependency ? (
    <DependencyWrapper
      {...SLOT}
      key={adjustedSlotName}
      name={adjustedSlotName}
      dependency={
        SLOT.dependency.conditions && {
          conditions: [
            {
              ...SLOT.dependency.conditions[0],
              name: `${prefix}${SLOT.dependency.conditions[0].name}`,
            },
          ],
          effect: SLOT.dependency.effect,
        }
      }
    >
      {formField}
    </DependencyWrapper>
  ) : (
    formField
  );
};