{"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 {Validation, ValidationErrors, ValidationFunction, ValidationResult} 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  /** Updates the current validation result. Not displayed to the user until `commitValidation` is called. */\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 {realtimeValidation, displayValidation, updateValidation, resetValidation, commitValidation} = props[privateValidationStateProp] as FormValidationState;\n    return {realtimeValidation, displayValidation, updateValidation, resetValidation, commitValidation};\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 {isInvalid, validationState, name, value, builtinValidation, validate, validationBehavior = 'aria'} = 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 = isInvalid !== undefined ? {\n    isInvalid,\n    validationErrors: [],\n    validationDetails: CUSTOM_VALIDITY_STATE\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) ? name.flatMap(name => asArray(serverErrors[name])) : 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 = controlledError || serverError || clientError || builtinValidation || DEFAULT_VALIDATION_RESULT;\n  let displayValidation = 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    isInvalid: true,\n    validationErrors: errors,\n    validationDetails: CUSTOM_VALIDITY_STATE\n  } : null;\n}\n\nfunction isEqualValidation(a: ValidationResult | null, b: ValidationResult | null): boolean {\n  if (a === b) {\n    return true;\n  }\n\n  return !!a && !!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\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.cjs.map"}