{"mappings":"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","sources":["packages/react-stately/src/form/useFormValidationState.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 {Context, createContext, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {\n  Validation,\n  ValidationErrors,\n  ValidationFunction,\n  ValidationResult\n} from '@react-types/shared';\n\nexport const VALID_VALIDITY_STATE: ValidityState = {\n  badInput: false,\n  customError: false,\n  patternMismatch: false,\n  rangeOverflow: false,\n  rangeUnderflow: false,\n  stepMismatch: false,\n  tooLong: false,\n  tooShort: false,\n  typeMismatch: false,\n  valueMissing: false,\n  valid: true\n};\n\nconst CUSTOM_VALIDITY_STATE: ValidityState = {\n  ...VALID_VALIDITY_STATE,\n  customError: true,\n  valid: false\n};\n\nexport const DEFAULT_VALIDATION_RESULT: ValidationResult = {\n  isInvalid: false,\n  validationDetails: VALID_VALIDITY_STATE,\n  validationErrors: []\n};\n\nexport const FormValidationContext: Context<ValidationErrors> = createContext<ValidationErrors>({});\n\n// Private props that we pass from useFormValidationState to children.\n// Ideally we'd use a Symbol for this, but React doesn't support them: https://github.com/facebook/react/issues/7552\n// This needs to be stable across server and client module evaluation for SSR hydration.\nexport const privateValidationStateProp: string = '__reactAriaFormValidationState';\n\ninterface FormValidationProps<T> extends Validation<T> {\n  builtinValidation?: ValidationResult;\n  name?: string | string[];\n  value: T | null;\n}\n\nexport interface FormValidationState {\n  /** Realtime validation results, updated as the user edits the value. */\n  realtimeValidation: ValidationResult;\n  /** Currently displayed validation results, updated when the user commits their changes. */\n  displayValidation: ValidationResult;\n  /**\n   * Updates the current validation result. Not displayed to the user until `commitValidation` is\n   * called.\n   */\n  updateValidation(result: ValidationResult): void;\n  /** Resets the displayed validation state to valid when the user resets the form. */\n  resetValidation(): void;\n  /** Commits the realtime validation so it is displayed to the user. */\n  commitValidation(): void;\n}\n\nexport function useFormValidationState<T>(props: FormValidationProps<T>): FormValidationState {\n  // Private prop for parent components to pass state to children.\n  if (props[privateValidationStateProp]) {\n    let {\n      realtimeValidation,\n      displayValidation,\n      updateValidation,\n      resetValidation,\n      commitValidation\n    } = props[privateValidationStateProp] as FormValidationState;\n    return {\n      realtimeValidation,\n      displayValidation,\n      updateValidation,\n      resetValidation,\n      commitValidation\n    };\n  }\n\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  return useFormValidationStateImpl(props);\n}\n\nfunction useFormValidationStateImpl<T>(props: FormValidationProps<T>): FormValidationState {\n  let {\n    isInvalid,\n    validationState,\n    name,\n    value,\n    builtinValidation,\n    validate,\n    validationBehavior = 'aria'\n  } = props;\n\n  // backward compatibility.\n  if (validationState) {\n    isInvalid ||= validationState === 'invalid';\n  }\n\n  // If the isInvalid prop is controlled, update validation result in realtime.\n  let controlledError: ValidationResult | null =\n    isInvalid !== undefined\n      ? {\n          isInvalid,\n          validationErrors: [],\n          validationDetails: CUSTOM_VALIDITY_STATE\n        }\n      : null;\n\n  // Perform custom client side validation.\n  let clientError: ValidationResult | null = useMemo(() => {\n    if (!validate || value == null) {\n      return null;\n    }\n    let validateErrors = runValidate(validate, value);\n    return getValidationResult(validateErrors);\n  }, [validate, value]);\n\n  if (builtinValidation?.validationDetails.valid) {\n    builtinValidation = undefined;\n  }\n\n  // Get relevant server errors from the form.\n  let serverErrors = useContext(FormValidationContext);\n  let serverErrorMessages = useMemo(() => {\n    if (name) {\n      return Array.isArray(name)\n        ? name.flatMap(name => asArray(serverErrors[name]))\n        : asArray(serverErrors[name]);\n    }\n    return [];\n  }, [serverErrors, name]);\n\n  // Show server errors when the form gets a new value, and clear when the user changes the value.\n  let [lastServerErrors, setLastServerErrors] = useState(serverErrors);\n  let [isServerErrorCleared, setServerErrorCleared] = useState(false);\n  if (serverErrors !== lastServerErrors) {\n    setLastServerErrors(serverErrors);\n    setServerErrorCleared(false);\n  }\n\n  let serverError: ValidationResult | null = useMemo(\n    () => getValidationResult(isServerErrorCleared ? [] : serverErrorMessages),\n    [isServerErrorCleared, serverErrorMessages]\n  );\n\n  // Track the next validation state in a ref until commitValidation is called.\n  let nextValidation = useRef(DEFAULT_VALIDATION_RESULT);\n  let [currentValidity, setCurrentValidity] = useState(DEFAULT_VALIDATION_RESULT);\n\n  let lastError = useRef(DEFAULT_VALIDATION_RESULT);\n  let commitValidation = () => {\n    if (!commitQueued) {\n      return;\n    }\n\n    setCommitQueued(false);\n    let error = clientError || builtinValidation || nextValidation.current;\n    if (!isEqualValidation(error, lastError.current)) {\n      lastError.current = error;\n      setCurrentValidity(error);\n    }\n  };\n\n  let [commitQueued, setCommitQueued] = useState(false);\n  useEffect(commitValidation);\n\n  // realtimeValidation is used to update the native input element's state based on custom validation logic.\n  // displayValidation is the currently displayed validation state that the user sees (e.g. on input change/form submit).\n  // With validationBehavior=\"aria\", all errors are displayed in realtime rather than on submit.\n  let realtimeValidation =\n    controlledError || serverError || clientError || builtinValidation || DEFAULT_VALIDATION_RESULT;\n  let displayValidation =\n    validationBehavior === 'native'\n      ? controlledError || serverError || currentValidity\n      : controlledError || serverError || clientError || builtinValidation || currentValidity;\n\n  return {\n    realtimeValidation,\n    displayValidation,\n    updateValidation(value) {\n      // If validationBehavior is 'aria', update in realtime. Otherwise, store in a ref until commit.\n      if (validationBehavior === 'aria' && !isEqualValidation(currentValidity, value)) {\n        setCurrentValidity(value);\n      } else {\n        nextValidation.current = value;\n      }\n    },\n    resetValidation() {\n      // Update the currently displayed validation state to valid on form reset,\n      // even if the native validity says it isn't. It'll show again on the next form submit.\n      let error = DEFAULT_VALIDATION_RESULT;\n      if (!isEqualValidation(error, lastError.current)) {\n        lastError.current = error;\n        setCurrentValidity(error);\n      }\n\n      // Do not commit validation after the next render. This avoids a condition where\n      // useSelect calls commitValidation inside an onReset handler.\n      if (validationBehavior === 'native') {\n        setCommitQueued(false);\n      }\n\n      setServerErrorCleared(true);\n    },\n    commitValidation() {\n      // Commit validation state so the user sees it on blur/change/submit. Also clear any server errors.\n      // Wait until after the next render to commit so that the latest value has been validated.\n      if (validationBehavior === 'native') {\n        setCommitQueued(true);\n      }\n      setServerErrorCleared(true);\n    }\n  };\n}\n\nfunction asArray<T>(v: T | T[]): T[] {\n  if (!v) {\n    return [];\n  }\n\n  return Array.isArray(v) ? v : [v];\n}\n\nfunction runValidate<T>(validate: ValidationFunction<T>, value: T): string[] {\n  if (typeof validate === 'function') {\n    let e = validate(value);\n    if (e && typeof e !== 'boolean') {\n      return asArray(e);\n    }\n  }\n\n  return [];\n}\n\nfunction getValidationResult(errors: string[]): ValidationResult | null {\n  return errors.length\n    ? {\n        isInvalid: true,\n        validationErrors: errors,\n        validationDetails: CUSTOM_VALIDITY_STATE\n      }\n    : null;\n}\n\nfunction isEqualValidation(a: ValidationResult | null, b: ValidationResult | null): boolean {\n  if (a === b) {\n    return true;\n  }\n\n  return (\n    !!a &&\n    !!b &&\n    a.isInvalid === b.isInvalid &&\n    a.validationErrors.length === b.validationErrors.length &&\n    a.validationErrors.every((a, i) => a === b.validationErrors[i]) &&\n    Object.entries(a.validationDetails).every(([k, v]) => b.validationDetails[k] === v)\n  );\n}\n\nexport function mergeValidation(...results: ValidationResult[]): ValidationResult {\n  let errors = new Set<string>();\n  let isInvalid = false;\n  let validationDetails = {\n    ...VALID_VALIDITY_STATE\n  };\n\n  for (let v of results) {\n    for (let e of v.validationErrors) {\n      errors.add(e);\n    }\n\n    // Only these properties apply for checkboxes.\n    isInvalid ||= v.isInvalid;\n    for (let key in validationDetails) {\n      validationDetails[key] ||= v.validationDetails[key];\n    }\n  }\n\n  validationDetails.valid = !isInvalid;\n  return {\n    isInvalid,\n    validationErrors: [...errors],\n    validationDetails\n  };\n}\n"],"names":[],"version":3,"file":"useFormValidationState.mjs.map"}