vcc-ui
Version:
A React library for building user interfaces at Volvo Cars
105 lines (103 loc) • 2.95 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useField = useField;
var _fastLoops = require("fast-loops");
var _react = require("react");
function validateField(validation, value) {
return (0, _fastLoops.objectReduce)(validation, (error, validate, message) => {
// early return to skip the rest once the first validation failed
if (error) {
return error;
}
if (validate instanceof RegExp) {
if (typeof value === 'string' && value.match(validate) === null) {
return message;
}
} else if (!validate(value)) {
return message;
}
}, undefined);
}
function useField(_ref) {
let {
name,
value = '',
touched = false,
disabled = false,
required = false,
loading,
showValidationOn,
requiredErrorMessage = 'This field is required.',
validation = {}
} = _ref;
const type = typeof value;
// add a special validation for required fields where the browser doesn't auto catch
if (required) {
validation[requiredErrorMessage] = value => type === 'string' ? value.length > 0 : type === 'boolean' ? value : true;
}
const errorMessage = validateField(validation, value);
const initial = {
value,
errorMessage,
isLoading: loading,
isDisabled: disabled,
isTouched: touched,
isRequired: required,
isValid: !errorMessage && !loading
};
const [field, setField] = (0, _react.useState)(initial);
const touch = () => setField(field => ({
...field,
isTouched: true
}));
const untouch = () => setField(field => ({
...field,
isTouched: false
}));
const update = values => setField(field => ({
...field,
...values
}));
function onChange(event) {
const newValue = type === 'boolean' ? event.target.checked : event.target.value;
const dirty = newValue !== value;
const errorMessage = validateField(validation, newValue);
setField(field => ({
...field,
value: newValue,
errorMessage,
isTouched: showValidationOn === 'change' ? dirty : field.isTouched,
isValid: !errorMessage && !field.isLoading
}));
}
const props = {
name,
[type === 'boolean' ? 'checked' : 'value']: field.value,
...(type !== 'boolean' && {
loading: field.isLoading
}),
disabled: field.isDisabled,
required: field.isRequired,
// only show errrorMessage and validation styles if the field is touched according to the config
errorMessage: field.isTouched ? field.errorMessage : undefined,
isValid: field.isTouched ? !field.errorMessage : true,
onChange
};
// by default, we always hide validation errors once the field is focused again
props.onFocus = untouch;
if (showValidationOn === 'blur') {
props.onBlur = touch;
}
return {
// we expose those values for debugging reasons
...field,
initial,
name,
props,
update,
touch,
untouch
};
}
;