@mantine/form
Version:
Mantine form management library
95 lines (94 loc) • 3.58 kB
JavaScript
"use client";
import { getInputOnChange } from "./get-input-on-change/get-input-on-change.mjs";
import { shouldValidateOnChange } from "./validate/should-validate-on-change.mjs";
import { useCallback, useMemo, useRef, useState } from "react";
//#region packages/@mantine/form/src/use-field.ts
function useField({ mode = "controlled", clearErrorOnChange = true, initialValue, initialError = null, initialTouched = false, onValueChange, validateOnChange = false, validateOnBlur = false, validate, resolveValidationError, type = "input" }) {
const [valueState, setValueState] = useState(initialValue);
const valueRef = useRef(valueState);
const [key, setKey] = useState(0);
const [error, setError] = useState(initialError || null);
const touchedRef = useRef(initialTouched || false);
const [, setTouchedState] = useState(touchedRef.current);
const [isValidating, setIsValidating] = useState(false);
const errorResolver = useMemo(() => resolveValidationError || ((err) => err), [resolveValidationError]);
const setTouched = useCallback((val, { updateState = mode === "controlled" } = {}) => {
touchedRef.current = val;
updateState && setTouchedState(val);
}, []);
const setValue = useCallback((value, { updateKey = mode === "uncontrolled", updateState = mode === "controlled" } = {}) => {
if (valueRef.current === value) return;
valueRef.current = value;
onValueChange?.(value);
if (clearErrorOnChange && error !== null) setError(null);
if (updateState) setValueState(value);
if (updateKey) setKey((currentKey) => currentKey + 1);
if (validateOnChange) _validate();
}, [
error,
clearErrorOnChange,
onValueChange
]);
const reset = useCallback(() => {
setValue(initialValue);
setError(null);
setTouched(false);
}, [initialValue]);
const getValue = useCallback(() => valueRef.current, []);
const isTouched = useCallback(() => touchedRef.current, []);
const isDirty = useCallback(() => valueRef.current !== initialValue, [initialValue]);
const _validate = useCallback(async () => {
const validationResult = validate?.(valueRef.current);
if (validationResult instanceof Promise) {
setIsValidating(true);
try {
const result = await validationResult;
setIsValidating(false);
setError(result);
} catch (err) {
setIsValidating(false);
const resolvedError = errorResolver(err);
setError(resolvedError);
return resolvedError;
}
} else {
setError(validationResult);
return validationResult;
}
}, []);
const getInputProps = ({ withError = true, withFocus = true, ...otherOptions } = {}) => {
const payload = { onChange: getInputOnChange((val) => setValue(val, { updateKey: false })) };
if (withError) payload.error = error;
if (type === "checkbox") payload[mode === "controlled" ? "checked" : "defaultChecked"] = valueRef.current;
else if (type === "radio") {
payload[mode === "controlled" ? "checked" : "defaultChecked"] = valueRef.current === otherOptions.value;
payload.value = otherOptions.value;
} else payload[mode === "controlled" ? "value" : "defaultValue"] = valueRef.current;
if (withFocus) {
payload.onFocus = () => {
setTouched(true);
};
payload.onBlur = () => {
if (shouldValidateOnChange("", !!validateOnBlur)) _validate();
};
}
return payload;
};
return {
key,
getValue,
setValue,
reset,
getInputProps,
isValidating,
validate: _validate,
error,
setError,
isTouched,
isDirty,
resetTouched: useCallback(() => setTouched(false), [])
};
}
//#endregion
export { useField };
//# sourceMappingURL=use-field.mjs.map