{"mappings":"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","sources":["packages/react-aria/src/form/useFormValidation.ts"],"sourcesContent":["/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {FormValidationState} from 'react-stately/private/form/useFormValidationState';\n\nimport {getEventTarget} from '../utils/shadowdom/DOMFunctions';\nimport {RefObject, Validation, ValidationResult} from '@react-types/shared';\nimport {setInteractionModality} from '../interactions/useFocusVisible';\nimport {useEffect, useRef} from 'react';\nimport {useEffectEvent} from '../utils/useEffectEvent';\nimport {useLayoutEffect} from '../utils/useLayoutEffect';\n\ntype ValidatableElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n\ninterface FormValidationProps<T> extends Validation<T> {\n  focus?: () => void\n}\n\nexport function useFormValidation<T>(props: FormValidationProps<T>, state: FormValidationState, ref: RefObject<ValidatableElement | null> | undefined): void {\n  let {validationBehavior, focus} = props;\n\n  // This is a useLayoutEffect so that it runs before the useEffect in useFormValidationState, which commits the validation change.\n  useLayoutEffect(() => {\n    if (validationBehavior === 'native' && ref?.current && !ref.current.disabled) {\n      let errorMessage = state.realtimeValidation.isInvalid ? state.realtimeValidation.validationErrors.join(' ') || 'Invalid value.' : '';\n      ref.current.setCustomValidity(errorMessage);\n\n      // Prevent default tooltip for validation message.\n      // https://bugzilla.mozilla.org/show_bug.cgi?id=605277\n      if (!ref.current.hasAttribute('title')) {\n        ref.current.title = '';\n      }\n\n      if (!state.realtimeValidation.isInvalid) {\n        state.updateValidation(getNativeValidity(ref.current));\n      }\n    }\n  });\n\n  let isIgnoredReset = useRef(false);\n  let onReset = useEffectEvent(() => {\n    if (!isIgnoredReset.current) {\n      state.resetValidation();\n    }\n  });\n\n  let onInvalid = useEffectEvent((e: Event) => {\n    // Only commit validation if we are not already displaying one.\n    // This avoids clearing server errors that the user didn't actually fix.\n    if (!state.displayValidation.isInvalid) {\n      state.commitValidation();\n    }\n\n    // Auto focus the first invalid input in a form, unless the error already had its default prevented.\n    let form = ref?.current?.form;\n    if (!e.defaultPrevented && ref && form && getFirstInvalidInput(form) === ref.current) {\n      if (focus) {\n        focus();\n      } else {\n        ref.current?.focus();\n      }\n\n      // Always show focus ring.\n      setInteractionModality('keyboard');\n    }\n\n    // Prevent default browser error UI from appearing.\n    e.preventDefault();\n  });\n\n  let onChange = useEffectEvent(() => {\n    state.commitValidation();\n  });\n\n  useEffect(() => {\n    let input = ref?.current;\n    if (!input) {\n      return;\n    }\n\n    let form = input.form;\n\n    let reset = form?.reset;\n    if (form) {\n      // Try to detect React's automatic form reset behavior so we don't clear\n      // validation errors that are returned by server actions.\n      // To do this, we ignore programmatic form resets that occur outside a user event.\n      // This is best-effort. There may be false positives, e.g. setTimeout.\n      form.reset = () => {\n        // React uses MessageChannel for scheduling, so ignore 'message' events.\n        isIgnoredReset.current = !window.event || (window.event.type === 'message' && getEventTarget(window.event) instanceof MessagePort);\n        reset?.call(form);\n        isIgnoredReset.current = false;\n      };\n    }\n\n    input.addEventListener('invalid', onInvalid);\n    input.addEventListener('change', onChange);\n    form?.addEventListener('reset', onReset);\n    return () => {\n      input!.removeEventListener('invalid', onInvalid);\n      input!.removeEventListener('change', onChange);\n      form?.removeEventListener('reset', onReset);\n      if (form) {\n        // @ts-ignore\n        form.reset = reset;\n      }\n    };\n  }, [ref, validationBehavior]);\n}\n\nfunction getValidity(input: ValidatableElement) {\n  // The native ValidityState object is live, meaning each property is a getter that returns the current state.\n  // We need to create a snapshot of the validity state at the time this function is called to avoid unpredictable React renders.\n  let validity = input.validity;\n  return {\n    badInput: validity.badInput,\n    customError: validity.customError,\n    patternMismatch: validity.patternMismatch,\n    rangeOverflow: validity.rangeOverflow,\n    rangeUnderflow: validity.rangeUnderflow,\n    stepMismatch: validity.stepMismatch,\n    tooLong: validity.tooLong,\n    tooShort: validity.tooShort,\n    typeMismatch: validity.typeMismatch,\n    valueMissing: validity.valueMissing,\n    valid: validity.valid\n  };\n}\n\nfunction getNativeValidity(input: ValidatableElement): ValidationResult {\n  return {\n    isInvalid: !input.validity.valid,\n    validationDetails: getValidity(input),\n    validationErrors: input.validationMessage ? [input.validationMessage] : []\n  };\n}\n\nfunction getFirstInvalidInput(form: HTMLFormElement): ValidatableElement | null {\n  for (let i = 0; i < form.elements.length; i++) {\n    let element = form.elements[i] as ValidatableElement;\n    if (element.validity?.valid === false) {\n      return element;\n    }\n  }\n\n  return null;\n}\n"],"names":[],"version":3,"file":"useFormValidation.mjs.map"}