{"version":3,"file":"useFormValidation.mjs","sources":[""],"sourcesContent":["import type {\r\n  Dispatch, SetStateAction, RefObject,\r\n} from \"react\";\r\nimport {\r\n  useEffect,\r\n  useState, useCallback,\r\n} from \"react\";\r\nimport { getElRefHelper } from \"./getElRefHelper\";\r\nimport { useListeners } from \"./useListeners\";\r\nimport { constants } from \"../../constants\";\r\nimport type { TValidationEvent as TInputValidationEvent, TValidationInput } from \"../../plugins/forms/validation\";\r\n\r\ntype TFormValidationEvent = CustomEvent<{\r\n  isValid: boolean;\r\n  inputs: TValidationInput[];\r\n}>;\r\n\r\ntype TValidationEntity = \"form\" | \"input\";\r\n\r\ntype TValidationEventMap = {\r\n  form: TFormValidationEvent;\r\n  input: TInputValidationEvent;\r\n};\r\n\r\ntype TValidState = boolean | null;\r\n\r\ntype TValidationResult = {\r\n  isValid: TValidState;\r\n  invalidInputNames: string[];\r\n  setIsValid: Dispatch<SetStateAction<TValidState>>;\r\n};\r\n\r\n/**\n * Добавляет валидацию на элемент формы либо на форму целиком и возвращает её результат\n * @template TType - тип источника валидации: `\"input\"` для отдельного поля или `\"form\"` для всей формы.\n * @returns {TValidationResult} Возвращает флаги валидации (`isValid`, `invalidInputNames`) и `setIsValid` для ручного сброса состояния.\n * @example\n * import { useRef } from \"react\";\r\n * import { useFormValidation } from \"@delement/ui/utils/react\";\r\n * import { Form, FormRow, Btn, Input } from \"@delement/ui/components\";\r\n *\r\n * const App = () => {\r\n *\r\n *   const ref = useRef(null);\r\n *   const { isValid, invalidInputNames } = useFormValidation(ref, null, \"form\"); // invalidInputNames содержит массив полей с ошибками\r\n *\r\n *   return (\r\n *     <Form ref={ref}>\r\n *       <FormRow>\r\n *         <Input name={\"test1\"} value={\"\"} isRequired={true}/>\r\n *       </FormRow>\r\n *       <FormRow>\r\n *         <Input name={\"test2\"} value={\"\"} isRequired={true}/>\r\n *       </FormRow>\r\n *       <FormRow>\r\n *         <Btn label={\"Отправить\"} type={\"submit\"}/>\r\n *       </FormRow>\r\n *     </Form>\r\n *   )\r\n * }\r\n */\r\nexport const useFormValidation = <TType extends TValidationEntity = \"input\">(\r\n  ref: RefObject<unknown>,\r\n  onValidate: ((event: TValidationEventMap[TType]) => void) | null = null,\r\n  type: TType = \"input\" as TType\r\n): TValidationResult => {\r\n\r\n  const [ isValid, setIsValid ] = useState<TValidationResult[\"isValid\"]>(null);\r\n  const [ invalidInputNames, setInvalidInputNames ] = useState<TValidationResult[\"invalidInputNames\"]>([]);\r\n\r\n  // robust preventing of re-render\r\n  const updateClassnames = (isValid: TValidationResult[\"isValid\"] = null) => {\r\n    const el = getElRefHelper(ref);\r\n    if (el) {\r\n      if (isValid === null) { // unknown validation state\r\n        el.classList.remove(constants.stateClasses.invalid, constants.stateClasses.valid);\r\n      } else { // validation is boolean\r\n        el.classList.toggle(constants.stateClasses.invalid, !isValid);\r\n        el.classList.toggle(constants.stateClasses.valid, isValid);\r\n      }\r\n    }\r\n  };\r\n\r\n  const handleValidate = useCallback((event: TValidationEventMap[TType]) => {\r\n    if (typeof onValidate === \"function\") {\r\n      onValidate(event);\r\n    } else {\r\n      const el = getElRefHelper(ref);\r\n      if (el) {\r\n        const isValid = event.detail.isValid;\r\n        // robust preventing of re-render\r\n        updateClassnames(isValid);\r\n        setIsValid(() => isValid);\r\n        if (type === \"form\") {\r\n          const inputs = \"inputs\" in event.detail ? event.detail.inputs : [];\r\n          const invalidInputNames = inputs.filter((input) => input.classList.contains(constants.stateClasses.invalid)).map(({ name }) => name);\r\n          setInvalidInputNames(() => invalidInputNames);\r\n        } else {\r\n          setInvalidInputNames(() => []);\r\n        }\r\n      } else {\r\n        console.error(\"[useFormValidation] Invalid ref\");\r\n      }\r\n    }\r\n  }, [ ref, onValidate, type ]);\r\n\r\n  useListeners<TValidationEventMap[TType]>({\r\n    listeners: {\r\n      [constants.formBubbles[type === \"input\" ? \"inputValid\" : \"formValid\"]]: handleValidate,\r\n      [constants.formBubbles[type === \"input\" ? \"inputInvalid\" : \"formInvalid\"]]: handleValidate,\r\n    },\r\n    ref,\r\n  });\r\n\r\n  useEffect(() => {\r\n    return () => {\r\n      setIsValid(null);\r\n      setInvalidInputNames([]);\r\n    };\r\n  }, []);\r\n\r\n  return {\r\n    isValid,\r\n    invalidInputNames,\r\n    setIsValid,\r\n  };\r\n\r\n};\r\n"],"names":["useFormValidation","ref","onValidate","type","isValid","setIsValid","useState","invalidInputNames","setInvalidInputNames","updateClassnames","el","getElRefHelper","classList","remove","constants","stateClasses","invalid","valid","toggle","handleValidate","useCallback","event","detail","inputs","filter","input","contains","map","name","console","error","useListeners","listeners","formBubbles","useEffect"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DO,MAAMA,kBAAoB,CAC/BC,IACAC,WAAmE,KACnEC,KAAc,WAGd,MAAQC,QAASC,YAAeC,SAAuC,MACvE,MAAQC,kBAAmBC,sBAAyBF,SAAiD;iCAGrG;MAAMG,iBAAmB,CAACL,QAAwC,QAChE,MAAMM,GAAKC,eAAeV,KAC1B,GAAIS,GACF,GAAIN,UAAY;;AACdM,GAAGE,UAAUC,OAAOC,UAAUC,aAAaC,QAASF,UAAUC,aAAaE,WACtE;;AACLP,GAAGE,UAAUM,OAAOJ,UAAUC,aAAaC,SAAUZ,SACrDM,GAAGE,UAAUM,OAAOJ,UAAUC,aAAaE,MAAOb,QACpD,GAIJ,MAAMe,eAAiBC,YAAaC,QAClC,UAAWnB,aAAe,WACxBA,WAAWmB,WACN,CACL,MAAMX,GAAKC,eAAeV,KAC1B,GAAIS,GAAI,CACN,MAAMN,QAAUiB,MAAMC,OAAOlB;iCAE7BK;iBAAiBL,SACjBC,WAAW,IAAMD,SACjB,GAAID,OAAS,OAAQ,CACnB,MAAMoB,OAAS,WAAYF,MAAMC,OAASD,MAAMC,OAAOC,OAAS,GAChE,MAAMhB,kBAAoBgB,OAAOC,OAAQC,OAAUA,MAAMb,UAAUc,SAASZ,UAAUC,aAAaC,UAAUW,IAAI,EAAGC,aAAWA,MAC/HpB,qBAAqB,IAAMD,kBAC7B,MACEC,qBAAqB,IAAM,GAE/B,MACEqB,QAAQC,MAAM,kCAElB,GACC,CAAE7B,IAAKC,WAAYC,OAEtB4B,aAAyC,CACvCC,UAAW,CACT,CAAClB,UAAUmB,YAAY9B,OAAS,QAAU,aAAe,cAAegB,eACxE,CAACL,UAAUmB,YAAY9B,OAAS,QAAU,eAAiB,gBAAiBgB,gBAE9ElB,UAGFiC,UAAU,IACD,KACL7B,WAAW,MACXG,qBAAqB,KAEtB,IAEH,MAAO,CACLJ,gBACAG,oCACAF"}