remix-hook-form
Version: 
Utility wrapper around react-hook-form for use with react-router v7+
208 lines (206 loc) • 6.79 kB
JavaScript
import {
  createFormData,
  generateFormData,
  getFormDataFromSearchParams,
  getValidatedFormData,
  parseFormData,
  validateFormData
} from "./chunk-RDVJQORD.js";
// src/hook/index.tsx
import React, {
  useEffect,
  useMemo,
  useState
} from "react";
import {
  FormProvider,
  get,
  useForm,
  useFormContext
} from "react-hook-form";
import {
  useActionData,
  useHref,
  useNavigation,
  useSubmit
} from "react-router";
var useRemixForm = ({
  submitHandlers,
  submitConfig,
  submitData,
  fetcher,
  stringifyAllValues = true,
  ...formProps
}) => {
  var _a, _b;
  const [isSubmittedSuccessfully, setIsSubmittedSuccessfully] = useState(false);
  const basename = useHref("/");
  const actionSubmit = useSubmit();
  const actionData = useActionData();
  const submit = (_a = fetcher == null ? void 0 : fetcher.submit) != null ? _a : actionSubmit;
  const data = (_b = fetcher == null ? void 0 : fetcher.data) != null ? _b : actionData;
  const methods = useForm({ ...formProps, errors: data == null ? void 0 : data.errors });
  const navigation = useNavigation();
  const isSubmittingForm = useMemo(() => {
    var _a2, _b2;
    const navigationIsSubmitting = navigation.state !== "idle" && ((_a2 = navigation.formData) != null ? _a2 : navigation.json) !== void 0;
    const fetcherIsSubmitting = (fetcher == null ? void 0 : fetcher.state) !== "idle" && ((_b2 = fetcher == null ? void 0 : fetcher.formData) != null ? _b2 : fetcher == null ? void 0 : fetcher.json) !== void 0;
    return navigationIsSubmitting || fetcherIsSubmitting;
  }, [
    navigation.state,
    navigation.formData,
    navigation.json,
    fetcher == null ? void 0 : fetcher.state,
    fetcher == null ? void 0 : fetcher.formData,
    fetcher == null ? void 0 : fetcher.json
  ]);
  const [isSubmittingNetwork, setIsSubmittingNetwork] = useState(false);
  useEffect(() => {
    if (!isSubmittingForm) {
      setIsSubmittingNetwork(false);
    }
  }, [isSubmittingForm]);
  const onSubmit = useMemo(
    () => (data2, e, formEncType, formMethod, formAction) => {
      var _a2, _b2, _c, _d;
      setIsSubmittingNetwork(true);
      setIsSubmittedSuccessfully(true);
      const encType = (_a2 = submitConfig == null ? void 0 : submitConfig.encType) != null ? _a2 : formEncType;
      const method = (_c = (_b2 = submitConfig == null ? void 0 : submitConfig.method) != null ? _b2 : formMethod) != null ? _c : "post";
      const action = (_d = submitConfig == null ? void 0 : submitConfig.action) != null ? _d : formAction;
      const submitPayload = { ...data2, ...submitData };
      const formData = encType === "application/json" ? submitPayload : createFormData(submitPayload, stringifyAllValues);
      submit(formData, {
        ...submitConfig,
        method,
        encType,
        action
      });
    },
    [submit, submitConfig, submitData, stringifyAllValues]
  );
  const onInvalid = useMemo(() => () => {
  }, []);
  const formState = useMemo(
    () => ({
      get isDirty() {
        return methods.formState.isDirty;
      },
      get isLoading() {
        return methods.formState.isLoading;
      },
      get isSubmitted() {
        return methods.formState.isSubmitted;
      },
      get isSubmitSuccessful() {
        return isSubmittedSuccessfully || methods.formState.isSubmitSuccessful;
      },
      get isSubmitting() {
        return isSubmittingNetwork || methods.formState.isSubmitting;
      },
      get isValidating() {
        return methods.formState.isValidating;
      },
      get isValid() {
        return methods.formState.isValid;
      },
      get disabled() {
        return methods.formState.disabled;
      },
      get submitCount() {
        return methods.formState.submitCount;
      },
      get defaultValues() {
        return methods.formState.defaultValues;
      },
      get dirtyFields() {
        return methods.formState.dirtyFields;
      },
      get touchedFields() {
        return methods.formState.touchedFields;
      },
      get validatingFields() {
        return methods.formState.validatingFields;
      },
      get errors() {
        return methods.formState.errors;
      }
    }),
    [methods.formState, isSubmittedSuccessfully, isSubmittingNetwork]
  );
  const reset = useMemo(
    () => (values, options) => {
      setIsSubmittedSuccessfully(false);
      methods.reset(values, options);
    },
    [methods.reset]
  );
  const register = useMemo(
    () => (name, options) => {
      var _a2;
      const defaultValue = (_a2 = get(data == null ? void 0 : data.defaultValues, name)) != null ? _a2 : get(methods.formState.defaultValues, name);
      return {
        ...methods.register(name, options),
        ...!(options == null ? void 0 : options.disableProgressiveEnhancement) && {
          defaultValue: typeof defaultValue === "string" ? defaultValue : void 0,
          defaultChecked: typeof defaultValue === "boolean" ? defaultValue : void 0
        }
      };
    },
    [methods.register, data == null ? void 0 : data.defaultValues, methods.formState.defaultValues]
  );
  const handleSubmit = useMemo(
    () => (e) => {
      var _a2, _b2, _c, _d, _e;
      const encType = (_a2 = e == null ? void 0 : e.currentTarget) == null ? void 0 : _a2.enctype;
      const method = (_b2 = e == null ? void 0 : e.currentTarget) == null ? void 0 : _b2.method;
      const action = (_c = e == null ? void 0 : e.currentTarget) == null ? void 0 : _c.action.replace(
        `${window.location.origin}${basename === "/" ? "" : basename}`,
        ""
      );
      const onValidHandler = (_d = submitHandlers == null ? void 0 : submitHandlers.onValid) != null ? _d : onSubmit;
      const onInvalidHandler = (_e = submitHandlers == null ? void 0 : submitHandlers.onInvalid) != null ? _e : onInvalid;
      return methods.handleSubmit(
        (data2, e2) => onValidHandler(data2, e2, encType, method, action),
        onInvalidHandler
      )(e);
    },
    [methods.handleSubmit, submitHandlers, onSubmit, onInvalid, basename]
  );
  const hookReturn = useMemo(
    () => ({
      ...methods,
      handleSubmit,
      reset,
      register,
      formState
    }),
    [methods, handleSubmit, reset, register, formState]
  );
  return hookReturn;
};
var RemixFormProvider = ({
  children,
  ...props
}) => {
  return /* @__PURE__ */ React.createElement(FormProvider, { ...props }, children);
};
var useRemixFormContext = () => {
  const methods = useFormContext();
  return {
    ...methods,
    // biome-ignore lint/suspicious/noExplicitAny: <explanation>
    handleSubmit: methods.handleSubmit
  };
};
export {
  RemixFormProvider,
  createFormData,
  generateFormData,
  getFormDataFromSearchParams,
  getValidatedFormData,
  parseFormData,
  useRemixForm,
  useRemixFormContext,
  validateFormData
};