UNPKG

@mantine/form

Version:

Mantine form management library

295 lines (294 loc) 12.1 kB
"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