{"version":3,"sources":["../../src/use-form/index.ts"],"sourcesContent":["import { useRef } from 'react'\nimport { useAsyncFn } from '../use-async-fn'\nimport { useLatest } from '../use-latest'\nimport { useMount } from '../use-mount'\nimport { useRender } from '../use-render'\nimport { useStableFn } from '../use-stable-fn'\nimport { isFunction, noop } from '../utils/basic'\nimport { getFormStateFromDom, isValidFormChildElement, syncFormStateToDom } from './bind-dom'\n\nimport type { ChangeEvent, FormEvent, RefObject, SetStateAction } from 'react'\nimport type { ReactSetState } from '../use-safe-state'\n\nexport interface UseFormOptions<FormState extends object> {\n  /**\n   * Initial value of the form\n   *\n   * @defaultValue {}\n   */\n  initialValue?: FormState\n  /**\n   * Callback to be called when the form value changes\n   *\n   * @defaultValue undefined\n   */\n  onChange?(form: FormState): void\n  /**\n   * Callback to be called when the form is submitted\n   *\n   * @defaultValue undefined\n   */\n  onSubmit?(form: FormState): void\n  /**\n   * Callback to be called when the form is reset\n   *\n   * @defaultValue undefined\n   */\n  onReset?(): void\n  /**\n   * When use `nativeProps`, whether to prevent default when the form is submitted\n   *\n   * @defaultValue true\n   */\n  preventDefaultWhenSubmit?: boolean\n  /**\n   * Whether to emit change event when the form is reset\n   *\n   * @defaultValue false\n   *\n   * @deprecated will be removed in the next major version\n   */\n  triggerOnChangeWhenReset?: boolean\n}\n\nexport type UseFormReturnsNativeProps = {\n  /**\n   * Ref of the form element\n   */\n  ref: RefObject<HTMLFormElement | null>\n  /**\n   * Callback to be called when the form value changes\n   */\n  onChange(e: ChangeEvent<HTMLFormElement>): void\n  /**\n   * Callback to be called when the form is submitted\n   */\n  onSubmit(e: ChangeEvent<HTMLFormElement>): void\n  /**\n   * Callback to be called when the form is reset\n   */\n  onReset(e: ChangeEvent<HTMLFormElement>): void\n}\n\nexport interface UseFormReturns<FormState extends object> {\n  /**\n   * Whether the form is submitting\n   */\n  submitting: boolean\n  /**\n   * Set the new value of the whole form\n   */\n  setValue: ReactSetState<FormState>\n  /**\n   * Set a field value of the form\n   */\n  setFieldValue<Name extends keyof FormState>(name: Name, value: FormState[Name]): void\n  /**\n   * Reset the form to its initial value\n   */\n  reset(): void\n  /**\n   * Submit the form\n   */\n  submit(): void\n  /**\n   * Current value of the form\n   */\n  value: FormState\n  /**\n   * Initial value of the form\n   */\n  initialValue: FormState\n  /**\n   * handle form value changes\n   */\n  handleChange(form: FormState): void\n  /**\n   * handle form submit\n   */\n  handleSubmit(form: FormState): void\n  /**\n   * handle form reset\n   */\n  handleReset(): void\n  /**\n   * Check and report the native form validity, only valid for native form\n   */\n  reportValidity(): boolean\n  /**\n   * Check the native form validity, only valid for native form\n   */\n  checkValidity(): boolean\n  /**\n   * Native form related props\n   */\n  nativeProps: UseFormReturnsNativeProps\n}\n\n/**\n * A React Hook to manage form state with ease\n *\n * @param {UseFormOptions} options Options to customize the form behavior\n *\n * @since 1.7.0\n */\nexport function useForm<FormState extends object>(options: UseFormOptions<FormState> = {}): UseFormReturns<FormState> {\n  const {\n    initialValue = {} as FormState,\n    triggerOnChangeWhenReset = false,\n    preventDefaultWhenSubmit = true,\n    onChange = noop,\n    onReset = noop,\n    onSubmit = noop,\n  } = options\n\n  const render = useRender()\n  const formRef = useRef<HTMLFormElement>(null)\n  const formValueRef = useRef<FormState>(initialValue)\n\n  const latest = useLatest({\n    initialValue,\n    triggerOnChangeWhenReset,\n    preventDefaultWhenSubmit,\n    onChange,\n    onReset,\n  })\n\n  const setFormValue = useStableFn((value: FormState) => {\n    formValueRef.current = value\n    !formRef.current && render()\n  })\n\n  const submitFn = useAsyncFn(onSubmit)\n\n  const handleChange = useStableFn((form: FormState) => {\n    setFormValue(form)\n    latest.current.onChange(form)\n  })\n\n  const handleSubmit = useStableFn((form: FormState) => {\n    submitFn.run(form)\n  })\n\n  const submit = useStableFn(() => {\n    return submitFn.run(formValueRef.current)\n  })\n\n  const handleReset = useStableFn(() => {\n    setValue(latest.current.initialValue)\n\n    latest.current.onReset()\n\n    if (latest.current.triggerOnChangeWhenReset) {\n      latest.current.onChange(latest.current.initialValue)\n    }\n  })\n\n  const reset = useStableFn(() => {\n    handleReset()\n  })\n\n  const handleNativeChange = useStableFn((e: FormEvent<HTMLFormElement>) => {\n    if (!isValidFormChildElement(e.target) || !formRef.current) return\n    const nextForm = getFormStateFromDom<FormState>(formRef.current, latest.current.initialValue)\n    handleChange(nextForm)\n  })\n\n  const handleNativeSubmit = useStableFn((e: FormEvent<HTMLFormElement>) => {\n    if (latest.current.preventDefaultWhenSubmit) {\n      e.preventDefault()\n      e.stopPropagation()\n    }\n\n    handleSubmit(formValueRef.current)\n  })\n\n  const handleNativeReset = useStableFn((_e: FormEvent<HTMLFormElement>) => {\n    handleReset()\n  })\n\n  const setValue = useStableFn((form: SetStateAction<FormState>) => {\n    const nextForm = isFunction(form) ? form(formValueRef.current) : form\n\n    // for uncontrollable form (by using nativeProps)\n    formRef.current && syncFormStateToDom(formRef.current, nextForm, latest.current.initialValue)\n\n    handleChange(nextForm)\n  })\n\n  const setFieldValue = useStableFn(<Name extends keyof FormState>(name: Name, value: FormState[Name]) => {\n    if (formValueRef.current[name] === value) return\n\n    const nextForm = {\n      ...formValueRef.current,\n      [name]: value,\n    }\n\n    setValue(nextForm)\n  })\n\n  const checkValidity = useStableFn(() => {\n    if (!formRef.current) return false\n    return formRef.current.checkValidity()\n  })\n\n  const reportValidity = useStableFn(() => {\n    if (!formRef.current) return false\n    return formRef.current.reportValidity()\n  })\n\n  useMount(() => {\n    if (formRef.current) {\n      syncFormStateToDom(formRef.current, formValueRef.current, initialValue)\n    }\n  })\n\n  return {\n    get value() {\n      // use `getter` to prevent expiring state\n      return formValueRef.current\n    },\n    get submitting() {\n      // for dependencies collection\n      return submitFn.loading\n    },\n    initialValue,\n    reset,\n    submit,\n    setValue,\n    setFieldValue,\n    handleReset,\n    handleSubmit,\n    handleChange,\n    checkValidity,\n    reportValidity,\n    nativeProps: {\n      ref: formRef,\n      onChange: handleNativeChange,\n      onSubmit: handleNativeSubmit,\n      onReset: handleNativeReset,\n    },\n  }\n}\n"],"names":["useForm","options","initialValue","triggerOnChangeWhenReset","preventDefaultWhenSubmit","onChange","noop","onReset","onSubmit","render","useRender","formRef","useRef","formValueRef","latest","useLatest","setFormValue","useStableFn","value","current","submitFn","useAsyncFn","handleChange","form","handleSubmit","run","submit","handleReset","setValue","reset","handleNativeChange","e","isValidFormChildElement","target","nextForm","getFormStateFromDom","handleNativeSubmit","preventDefault","stopPropagation","handleNativeReset","_e","isFunction","syncFormStateToDom","setFieldValue","name","checkValidity","reportValidity","useMount","submitting","loading","nativeProps","ref"],"mappings":"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"}