{"version":3,"file":"useValidation.cjs","sources":["../../../../src/internal/inputs/useValidation.ts"],"sourcesContent":["import type {Dispatch, FormEvent, SetStateAction} from 'react';\nimport {useCallback, useState} from 'react';\nimport AwesomeDebouncePromise from 'awesome-debounce-promise';\n\nimport type {ValidationProps, ValidatorFn} from './ValidationProps.ts';\nimport {ValidationState} from './ValidationProps.ts';\nimport {defaultValidator} from './defaultValidator.ts';\nimport {useHandleFormReset} from './useHandleFormReset.ts';\nimport {getFormState} from './getFormState.ts';\n\ntype InputMode = 'interactive' | 'textual';\n\nconst getValue = <TEvent extends FormEvent, TElement extends HTMLInputElement>(\n    event: TEvent,\n    mode: InputMode\n) => {\n    return mode === 'interactive'\n        ? (event.target as TElement).checked\n        : (event.target as TElement).value;\n};\n\nconst useValidatorFn = <TEvent extends FormEvent, TElement extends HTMLInputElement>({\n    validatorFn,\n    reportValidity,\n    setValidity,\n}: {\n    validatorFn: ValidatorFn;\n    reportValidity: (event: TEvent) => void;\n    setValidity: Dispatch<SetStateAction<keyof typeof ValidationState>>;\n}) => {\n    const createValidatorSync = useCallback(\n        (mode: InputMode, event: TEvent) => {\n            const value = getValue(event, mode);\n            const formState = getFormState((event.target as TElement)!.form);\n            const validationError = validatorFn?.(\n                value,\n                (event.target as TElement).validity,\n                formState\n            );\n            (event.target as TElement).setCustomValidity(validationError as string);\n            reportValidity(event);\n        },\n        [validatorFn, reportValidity]\n    );\n\n    const createValidatorExternal = useCallback(() => {}, []);\n\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    const debouncedValidator = useCallback(AwesomeDebouncePromise(validatorFn!, 1000), [\n        validatorFn,\n    ]);\n\n    const createValidatorAsync = useCallback(\n        async (mode: InputMode, event: TEvent) => {\n            (event.target as TElement).setCustomValidity('');\n            const value = getValue(event, mode);\n            const formState = getFormState((event.target as TElement)!.form);\n            setValidity(ValidationState.inProgress);\n            let validationError = '';\n            try {\n                validationError = await debouncedValidator(\n                    value,\n                    (event.target as TElement).validity,\n                    formState\n                );\n            } catch (error) {\n                (event.target as TElement).setCustomValidity(error as string);\n            }\n            (event.target as TElement).setCustomValidity(validationError);\n            reportValidity(event);\n        },\n        [setValidity, debouncedValidator, reportValidity]\n    );\n\n    return {createValidatorSync, createValidatorAsync, createValidatorExternal};\n};\n\nconst createValidatorFn = (validation: ValidationProps['validation']): ValidatorFn => {\n    if (typeof validation === 'function') {\n        return validation;\n    }\n    return defaultValidator;\n};\n\nenum Modes {\n    async = 'async',\n    external = 'external',\n    sync = 'sync',\n}\n\nconst getMode = (validation: ValidationProps['validation']) => {\n    if (validation?.constructor.name === 'AsyncFunction') {\n        return Modes.async;\n    } else if (typeof validation === 'string') {\n        return Modes.external;\n    }\n\n    return Modes.sync;\n};\n\nexport const useValidation = <TEvent extends FormEvent, TElement extends HTMLInputElement>({\n    validation,\n    hasValidators,\n}: ValidationProps & {hasValidators: boolean}) => {\n    const validatorFn = createValidatorFn(validation);\n    const mode = getMode(validation);\n\n    const [validity, setValidity] = useState<keyof typeof ValidationState>(\n        ValidationState.pristine\n    );\n\n    useHandleFormReset(setValidity);\n\n    const reportValidity = useCallback(\n        (event: TEvent) => {\n            const isValid = (event.target as TElement).reportValidity();\n            const ValidState = hasValidators ? ValidationState.valid : ValidationState.pristine;\n            const nextValidationState = isValid ? ValidState : ValidationState.error;\n            /**\n             * Change state only when input has validators or is in the error state.\n             * This is required to avoid always showing a green checkmark for input without validation.\n             */\n            (hasValidators || validity === ValidationState.error) &&\n                setValidity(nextValidationState);\n        },\n        [hasValidators, validity]\n    );\n\n    const {createValidatorAsync, createValidatorSync, createValidatorExternal} = useValidatorFn({\n        validatorFn,\n        reportValidity,\n        setValidity,\n    });\n\n    const validateInteractive = useCallback(\n        (event: TEvent) => {\n            switch (mode) {\n                case 'sync': {\n                    return createValidatorSync('interactive', event);\n                }\n                case 'async': {\n                    return createValidatorAsync('interactive', event);\n                }\n                case 'external': {\n                    return createValidatorExternal();\n                }\n            }\n        },\n        [createValidatorAsync, createValidatorExternal, createValidatorSync, mode]\n    );\n\n    const validateTextual = useCallback(\n        (event: TEvent) => {\n            switch (mode) {\n                case 'sync': {\n                    return createValidatorSync('textual', event);\n                }\n                case 'async': {\n                    return createValidatorAsync('textual', event);\n                }\n                case 'external': {\n                    return createValidatorExternal();\n                }\n            }\n        },\n        [mode, createValidatorSync, createValidatorAsync, createValidatorExternal]\n    );\n\n    return {validateInteractive, validateTextual, validity, setValidity};\n};\n"],"names":["getValue","event","mode","useValidatorFn","validatorFn","reportValidity","setValidity","createValidatorSync","useCallback","value","formState","getFormState","validationError","createValidatorExternal","debouncedValidator","AwesomeDebouncePromise","createValidatorAsync","ValidationState","error","createValidatorFn","validation","defaultValidator","getMode","useValidation","hasValidators","validity","useState","useHandleFormReset","isValid","ValidState","nextValidationState","validateInteractive","validateTextual"],"mappings":"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"}