@andydowell/use-form-state
Version:
A React hook for managing form state and validation
216 lines (212 loc) • 7.32 kB
JavaScript
import { useState, useRef } from 'react';
function _extends() {
_extends = Object.assign ? Object.assign.bind() : function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
// --------------------------------------------------------------------
var useFormState = function useFormState(formFieldParams, options) {
if (options === void 0) {
options = {};
}
var _options = options,
_options$errorUpdateD = _options.errorUpdateDelayInSeconds,
errorUpdateDelayInSeconds = _options$errorUpdateD === void 0 ? 0.5 : _options$errorUpdateD;
var initialFormState = function () {
var _state = {};
for (var key in formFieldParams) {
_state[key] = {
value: formFieldParams[key].defaultValue,
label: formFieldParams[key].label || "",
helperText: formFieldParams[key].helperText,
isValid: false,
isInteracted: false,
isRequired: !!formFieldParams[key].required,
error: undefined
};
}
var _loop = function _loop(_key) {
switch (true) {
case _state[_key].isRequired && !checkIfRequiredValueFilled(_state[_key].value):
_state[_key].isValid = false;
break;
case Boolean(formFieldParams[_key].validation):
_state[_key].isValid = Object.values(formFieldParams[_key].validation).every(function (_ref) {
var validator = _ref.validator;
return validator(_state[_key].value, _state);
});
break;
default:
_state[_key].isValid = true;
}
};
for (var _key in formFieldParams) {
_loop(_key);
}
return _state;
}();
var _useState = useState(initialFormState),
state = _useState[0],
setState = _useState[1];
var inputDebounceRef = useRef();
// --------------------------------------------------------------------
var debouncedErrorUpdate = function debouncedErrorUpdate() {
runValidation({
updateErrorType: errorUpdateDelayInSeconds > 0 ? false : true
});
clearTimeout(inputDebounceRef.current);
if (errorUpdateDelayInSeconds > 0) {
inputDebounceRef.current = setTimeout(function () {
runValidation();
}, errorUpdateDelayInSeconds * 1000);
}
};
// --------------------------------------------------------------------
var set = function set(key, value, setInteracted) {
if (setInteracted === void 0) {
setInteracted = true;
}
setState(function (_state) {
_state[key].value = value;
if (setInteracted) _state[key].isInteracted = true;
return _extends({}, _state);
});
debouncedErrorUpdate();
};
// --------------------------------------------------------------------
var update = function update(data, setInteracted) {
if (setInteracted === void 0) {
setInteracted = true;
}
setState(function (_state) {
Object.entries(data).forEach(function (_ref2) {
var key = _ref2[0],
value = _ref2[1];
_state[key].value = value;
if (setInteracted) _state[key].isInteracted = true;
});
return _extends({}, _state);
});
debouncedErrorUpdate();
};
// --------------------------------------------------------------------
var runValidation = function runValidation(options) {
var _ref3 = options || {},
updateErrorType = _ref3.updateErrorType;
setState(function (_state) {
var _loop2 = function _loop2(key) {
var _formFieldParams$key$;
var shouldUpdateErrorType = updateErrorType != null ? updateErrorType : _state[key].isInteracted;
switch (true) {
case _state[key].isRequired && !checkIfRequiredValueFilled(_state[key].value):
_state[key].isValid = false;
_state[key].error = shouldUpdateErrorType ? {
type: "required",
message: (_formFieldParams$key$ = formFieldParams[key].required) == null ? void 0 : _formFieldParams$key$.message
} : _state[key].error;
break;
case Boolean(formFieldParams[key].validation):
var _error = undefined;
_state[key].isValid = Object.entries(formFieldParams[key].validation).every(function (_ref4) {
var validationType = _ref4[0],
_ref4$ = _ref4[1],
validator = _ref4$.validator,
message = _ref4$.message;
var isValidationPassed = validator(_state[key].value, _state);
if (!isValidationPassed) {
_error = {
type: validationType,
message: message || ""
};
}
return isValidationPassed;
});
_state[key].error = shouldUpdateErrorType ? _error : _state[key].error;
break;
default:
_state[key].isValid = true;
_state[key].error = shouldUpdateErrorType ? undefined : _state[key].error;
}
};
for (var key in _state) {
_loop2(key);
}
return _extends({}, _state);
});
};
// --------------------------------------------------------------------
var checkIfAllValid = function checkIfAllValid(options) {
var _ref5 = options || {},
_ref5$updateErrorType = _ref5.updateErrorType,
updateErrorType = _ref5$updateErrorType === void 0 ? true : _ref5$updateErrorType;
if (updateErrorType) {
runValidation({
updateErrorType: true
});
}
for (var key in state) {
if (!state[key].isValid) return false;
}
return true;
};
var extractStateValue = function extractStateValue(_ref6) {
var format = _ref6.format;
switch (format) {
case "formdata":
var formData = new FormData();
Object.entries(state).forEach(function (_ref7) {
var key = _ref7[0],
data = _ref7[1];
formData.append(key, data.value);
});
return formData;
case "object":
default:
var data = {};
for (var key in state) {
data[key] = state[key].value;
}
return data;
}
};
// --------------------------------------------------------------------
var reset = function reset() {
setState(initialFormState);
clearTimeout(inputDebounceRef.current);
};
// --------------------------------------------------------------------
return {
state: state,
set: set,
update: update,
checkIfAllValid: checkIfAllValid,
extractStateValue: extractStateValue,
reset: reset
};
};
var checkIfRequiredValueFilled = function checkIfRequiredValueFilled(value) {
switch (typeof value) {
case "number":
if (isNaN(value) || !Number.isFinite(value)) return false;
return true;
case "object":
if (Array.isArray(value)) return value.length > 0;
if (value == null) return false;
return Boolean(value);
case "string":
case "boolean":
default:
return Boolean(value);
}
};
export { useFormState };
//# sourceMappingURL=use-form-state.esm.js.map