@mantine/form
Version:
Mantine form management library
295 lines (294 loc) • 12.1 kB
JavaScript
"use client";
require("./_virtual/_rolldown/runtime.cjs");
const require_actions = require("./actions/actions.cjs");
const require_get_input_on_change = require("./get-input-on-change/get-input-on-change.cjs");
const require_use_form_errors = require("./hooks/use-form-errors/use-form-errors.cjs");
const require_get_path = require("./paths/get-path.cjs");
const require_get_data_path = require("./paths/get-data-path.cjs");
const require_use_form_list = require("./hooks/use-form-list/use-form-list.cjs");
const require_use_form_status = require("./hooks/use-form-status/use-form-status.cjs");
const require_use_form_validating = require("./hooks/use-form-validating/use-form-validating.cjs");
const require_use_form_values = require("./hooks/use-form-values/use-form-values.cjs");
const require_use_form_watch = require("./hooks/use-form-watch/use-form-watch.cjs");
const require_validate_values = require("./validate/validate-values.cjs");
const require_validate_field_value = require("./validate/validate-field-value.cjs");
const require_should_validate_on_change = require("./validate/should-validate-on-change.cjs");
let react = require("react");
//#region packages/@mantine/form/src/use-form.ts
const defaultResolveValidationError = (err) => err instanceof Error ? err.message : String(err);
function useForm({ name, mode = "controlled", initialValues, initialErrors = {}, initialDirty = {}, initialTouched = {}, clearInputErrorOnChange = true, validateInputOnChange = false, validateInputOnBlur = false, onValuesChange, transformValues = ((values) => values), enhanceGetInputProps, validate: rules, onSubmitPreventDefault = "always", touchTrigger = "change", cascadeUpdates = false, validateDebounce = 0, resolveValidationError = defaultResolveValidationError } = {}) {
const $errors = require_use_form_errors.useFormErrors(initialErrors);
const $values = require_use_form_values.useFormValues({
initialValues,
onValuesChange,
mode
});
const $status = require_use_form_status.useFormStatus({
initialDirty,
initialTouched,
$values,
mode
});
const $watch = require_use_form_watch.useFormWatch({
$values,
$status,
cascadeUpdates
});
const $list = require_use_form_list.useFormList({
$values,
$errors,
$status,
$watch
});
const $validating = require_use_form_validating.useFormValidating();
const [formKey, setFormKey] = (0, react.useState)(0);
const [fieldKeys, setFieldKeys] = (0, react.useState)({});
const [submitting, setSubmitting] = (0, react.useState)(false);
const validateGeneration = (0, react.useRef)(0);
const reset = (0, react.useCallback)(() => {
$values.resetValues();
$errors.clearErrors();
$status.resetDirty();
$status.resetTouched();
$validating.clearValidating();
mode === "uncontrolled" && setFormKey((key) => key + 1);
}, []);
const handleValuesChanges = (0, react.useCallback)((previousValues) => {
clearInputErrorOnChange && $errors.clearErrors();
mode === "uncontrolled" && setFormKey((key) => key + 1);
$watch.notifyWatchSubscribers(previousValues);
}, [clearInputErrorOnChange]);
const initialize = (0, react.useCallback)((values) => {
const previousValues = $values.refValues.current;
$values.initialize(values, () => mode === "uncontrolled" && setFormKey((key) => key + 1));
handleValuesChanges(previousValues);
}, [handleValuesChanges]);
const debouncedValidateField = (0, react.useMemo)(() => {
const timers = {};
const handleValidation = (path) => {
const signal = $validating.getAbortSignal(path);
const result = require_validate_field_value.validateFieldValue(path, rules, $values.refValues.current, resolveValidationError, signal);
const applyResult = (results) => {
if (signal.aborted) return;
if (results.hasError) $errors.setFieldError(path, results.error);
else $errors.clearFieldError(path);
};
const cleanup = () => {
if (!signal.aborted) $validating.setFieldValidating(path, false);
};
if (result instanceof Promise) {
$validating.setFieldValidating(path, true);
result.then(applyResult).finally(cleanup);
} else applyResult(result);
};
return (path) => {
clearTimeout(timers[path]);
if (validateDebounce > 0) timers[path] = setTimeout(() => handleValidation(path), validateDebounce);
else handleValidation(path);
};
}, [
validateDebounce,
rules,
resolveValidationError
]);
const setFieldValue = (0, react.useCallback)((path, value, options) => {
const shouldValidate = require_should_validate_on_change.shouldValidateOnChange(path, validateInputOnChange);
const resolvedValue = value instanceof Function ? value(require_get_path.getPath(path, $values.refValues.current)) : value;
$status.setCalculatedFieldDirty(path, resolvedValue);
touchTrigger === "change" && $status.setFieldTouched(path, true);
!shouldValidate && clearInputErrorOnChange && $errors.clearFieldError(path);
$values.setFieldValue({
path,
value,
updateState: mode === "controlled",
subscribers: [
...$watch.getFieldSubscribers(path),
shouldValidate ? () => debouncedValidateField(String(path)) : null,
options?.forceUpdate !== false && mode !== "controlled" ? () => setFieldKeys((keys) => ({
...keys,
[path]: (keys[path] || 0) + 1
})) : null
]
});
}, [
onValuesChange,
rules,
debouncedValidateField
]);
const setValues = (0, react.useCallback)((values) => {
const previousValues = $values.refValues.current;
$values.setValues({
values,
updateState: mode === "controlled"
});
handleValuesChanges(previousValues);
}, [onValuesChange, handleValuesChanges]);
const validate = (0, react.useCallback)(() => {
const generation = ++validateGeneration.current;
const signal = $validating.getAbortSignal("__form__");
const handleResult = (results) => {
if (generation !== validateGeneration.current) return {
hasErrors: false,
errors: {}
};
$errors.setErrors(results.errors);
return results;
};
const cleanup = () => {
if (generation === validateGeneration.current) $validating.setFormValidating(false);
};
const result = require_validate_values.validateValues(rules, $values.refValues.current, resolveValidationError, signal);
if (result instanceof Promise) {
$validating.setFormValidating(true);
return result.then(handleResult).finally(cleanup);
}
return handleResult(result);
}, [rules, resolveValidationError]);
const validateField = (0, react.useCallback)((path) => {
const signal = $validating.getAbortSignal(String(path));
const applyResult = (results) => {
if (signal.aborted) return {
hasError: false,
error: null
};
if (results.hasError) $errors.setFieldError(path, results.error);
else $errors.clearFieldError(path);
return results;
};
const cleanup = () => {
if (!signal.aborted) $validating.setFieldValidating(String(path), false);
};
const result = require_validate_field_value.validateFieldValue(path, rules, $values.refValues.current, resolveValidationError, signal);
if (result instanceof Promise) {
$validating.setFieldValidating(String(path), true);
return result.then(applyResult).finally(cleanup);
}
return applyResult(result);
}, [rules, resolveValidationError]);
const getInputProps = (path, { type = "input", withError = true, withFocus, ...otherOptions } = {}) => {
const _withFocus = withFocus ?? type !== "radio";
const payload = {
onChange: require_get_input_on_change.getInputOnChange((value) => setFieldValue(path, value, { forceUpdate: false })),
"data-path": require_get_data_path.getDataPath(name, path)
};
if (withError) payload.error = $errors.errorsState[path];
if (type === "checkbox") payload[mode === "controlled" ? "checked" : "defaultChecked"] = require_get_path.getPath(path, $values.refValues.current);
else if (type === "radio") {
payload[mode === "controlled" ? "checked" : "defaultChecked"] = require_get_path.getPath(path, $values.refValues.current) === otherOptions.value;
payload.value = otherOptions.value;
} else payload[mode === "controlled" ? "value" : "defaultValue"] = require_get_path.getPath(path, $values.refValues.current);
if (_withFocus) {
payload.onFocus = () => $status.setFieldTouched(path, true);
payload.onBlur = () => {
if (require_should_validate_on_change.shouldValidateOnChange(path, validateInputOnBlur)) debouncedValidateField(String(path));
};
}
return Object.assign(payload, enhanceGetInputProps?.({
inputProps: payload,
field: path,
options: {
type,
withError,
withFocus: _withFocus,
...otherOptions
},
form
}));
};
const onSubmit = (handleSubmit, handleValidationFailure) => (event) => {
if (onSubmitPreventDefault === "always") event?.preventDefault();
setSubmitting(true);
const handleValidation = (results) => {
if (results.hasErrors) {
if (onSubmitPreventDefault === "validation-failed") event?.preventDefault();
handleValidationFailure?.(results.errors, $values.refValues.current, event);
setSubmitting(false);
} else {
const submitResult = handleSubmit?.(transformValues($values.refValues.current), event);
if (submitResult instanceof Promise) submitResult.finally(() => setSubmitting(false));
else setSubmitting(false);
}
};
const result = validate();
if (result instanceof Promise) result.then(handleValidation).catch(() => {
setSubmitting(false);
});
else handleValidation(result);
};
const getTransformedValues = (input) => transformValues(input || $values.refValues.current);
const onReset = (0, react.useCallback)((event) => {
event.preventDefault();
reset();
}, []);
const isValid = (0, react.useCallback)((path) => {
const signal = new AbortController().signal;
if (path) {
const result = require_validate_field_value.validateFieldValue(path, rules, $values.refValues.current, resolveValidationError, signal);
if (result instanceof Promise) return result.then((r) => !r.hasError);
return !result.hasError;
}
const result = require_validate_values.validateValues(rules, $values.refValues.current, resolveValidationError, signal);
if (result instanceof Promise) return result.then((r) => !r.hasErrors);
return !result.hasErrors;
}, [rules, resolveValidationError]);
const key = (path) => `${formKey}-${String(path)}-${fieldKeys[String(path)] || 0}`;
const getInputNode = (0, react.useCallback)((path) => document.querySelector(`[data-path="${require_get_data_path.getDataPath(name, path)}"]`), []);
const resetField = (0, react.useCallback)((path) => {
$values.resetField(path, [mode !== "controlled" ? () => setFieldKeys((keys) => ({
...keys,
[path]: (keys[path] || 0) + 1
})) : null]);
}, [
$values.resetField,
mode,
setFieldKeys
]);
const form = {
watch: $watch.watch,
initialized: $values.initialized.current,
values: mode === "uncontrolled" ? $values.refValues.current : $values.stateValues,
getValues: $values.getValues,
getInitialValues: $values.getValuesSnapshot,
setInitialValues: $values.setValuesSnapshot,
resetField,
initialize,
setValues,
setFieldValue,
submitting,
setSubmitting,
validating: $validating.validating,
isValidating: $validating.isValidating,
errors: $errors.errorsState,
setErrors: $errors.setErrors,
setFieldError: $errors.setFieldError,
clearFieldError: $errors.clearFieldError,
clearErrors: $errors.clearErrors,
resetDirty: $status.resetDirty,
setTouched: $status.setTouched,
setDirty: $status.setDirty,
isTouched: $status.isTouched,
resetTouched: $status.resetTouched,
isDirty: $status.isDirty,
getTouched: $status.getTouched,
getDirty: $status.getDirty,
reorderListItem: $list.reorderListItem,
insertListItem: $list.insertListItem,
removeListItem: $list.removeListItem,
replaceListItem: $list.replaceListItem,
reset,
validate,
validateField,
getInputProps,
onSubmit,
onReset,
isValid,
getTransformedValues,
key,
getInputNode
};
require_actions.useFormActions(name, form);
return form;
}
//#endregion
exports.useForm = useForm;
//# sourceMappingURL=use-form.cjs.map